classes in Python: AttributeError - python-3.x

I`m writing simple scripts for test automation using Selenium WebDriver in Python, but the issue relates to Python, not to Selenium.
There two classes FindByXPATH_1(base) & FindByXPATH_2(derived). I want to call an attribute "driver" from the base class in a method of FindByXPATH_2, but when I ran the code the AttributeError shows up: "type object 'FindByXPATH_1' has no attribute 'driver'"
Here is the code:
class FindByXPATH_1():
def __init__(self):
self.driver_location = '/usr/local/bin/chromedriver'
self.driver = webdriver.Chrome(self.driver_location)
self.driver.get('https://letskodeit.teachable.com/p/practice')
from basics.xpath_1 import FindByXPATH_1
import basics #the classes are in two different python files
class FindByXpath_2(FindByXPATH_1):
def __init__(self):
FindByXPATH_1.__init__(self)
def find_by_starts_with(self):
starting_with = FindByXPATH_1.driver.find_elements(By. XPATH,
'//div[#class="view-school"]//h3[starts-with(#)class, "subtitle"]')
print(len(starting_with))
test = FindByXPATH_2()
test.find_by_starts_with()
After running the code I get a message "AttributeError: type object 'FindByXPATH_1' has no attribute 'driver'"
How can I call that attribute?

In this line here:
starting_with = FindByXPATH_1.driver.find_elements(By. XPATH,
'//div[#class="view-school"]//h3[starts-with(#)class, "subtitle"]')
You should be calling self.driver.find_elements otherwise you are trying to access a class variable of FindByXPATH_1 and not the instance variable driver

Related

Class Attributes Not Found Python

Here is my code:
Here is my error:
I'm very confused why this is happening. I'm using an instance of the class JinderBot and the __init__ function clearly sets the driver attribute. Please help point out my mistake.
I'm using PyCharm and Python 3.7.
You need to add methods to the class to access and set the attributes.
class JinderBot:
def __init__(self):
self.atrib = “foobar”
def _get(self):
return self.atrib
def _set(self, atrib)
self.atrib = atrib
bot = JinderBot()
print(bot._get())
bot._set(“updating attribute”)
print(bot._get())

AttributeError: object has no attribute - although class method exists

I have a class consisting of 14 methods. Here is the skeleton:
class Field
def __init__():
...
return
def ...():
country = Field()
country.re_fitness_population()
It's a large class, so here is the full pastebin.
Running this code results in:
----> 1 country.re_fitness_population()
AttributeError: 'Field' object has no attribute 're_fitness_population'
Running dir() on this class doesn't show the method as available, and I've tried fixing any spacing issues, but running python3 -tt also doesn't show anything. I've tried renaming the method, also doesn't help.
I clearly have written the function as one of the methods of the class. I feel like there is something big I'm missing.

PyCharm and proper type hinting of class objects

System:
- Windows 10 x64
- Python 3.6 x64
- PyCharm 2017.3.4
I am trying to better understand Python type annotation as relates to specifying class objects, rather than instances of classes. Suppose I have a super class and a sub class and I want to loop over a list of class objects and instantiate one of each.
In the code below I can get proper code-completion and tooltips in PyCharm when instantiating from the class directly or from a direct alias (using Ctrl-P for example). However, if I loop over the list and provide a type annotation (using typing.Type[Super1]) for the iterating variable cls it seems to annotate it as an instance, rather than as a class object. So I get proper code completion for the methods and properties, but then I don't get tooltips for the function arguments for the initialization.
How do I annotate it as a set of classes, rather than an instance of a set of classes (i.e. this variable is either the Super1 class or a sub-class of Super1). Is this the proper way but PyCharm just isn't recognizing it properly or is there actually a different way to do this.
import typing
class Super1:
def __init__(self, name: str):
self.name = name
self.meta = "super class"
def print_name(self):
print(self.name)
class Sub1(Super1):
def __init__(self, name: str):
super(Sub1, self).__init__(name)
self.meta = "sub class"
super_instance = Super1("name") # <-- get proper type hints in PyCharm
sub1_alias = Sub1
sub1_alias("name") # <-- get proper type hints for the __init__ function in PyCharm
cls: typing.Type[Super1]
for cls in (Super1, Sub1):
inst = cls("name") # <-- Ctrl-P does not give proper type hints for the __init__ function in PyCharm

How to override class attribute access in python3

I am trying to override class attribute access in python3. I found this question already answered for python2. But the same is not working with Python3. Please help me to understand why this does not work with Python3 and how to get it to work.
Here is the code i am trying to verify in Python3:
class BooType(type):
def __getattr__(self, attr):
print(attr)
return attr
class Boo(object):
__metaclass__ = BooType
boo = Boo()
Boo.asd #Raises AttributeError in Python3 where as in Python2 this prints 'asd'
from http://python-3-patterns-idioms-test.readthedocs.io/en/latest/Metaprogramming.html
Python 3 changes the metaclass hook. It doesn’t disallow the __metaclass__ field, but it ignores it. Instead, you use a keyword argument in the base-class list:
in your case, you have to change to:
class Boo(object, metaclass = BooType):
pass
and that works. This syntax isn't compatible with python 2, though.
There's a way to create compatible code, seen in http://python-future.org/compatible_idioms.html#metaclasses
# Python 2 and 3:
from six import with_metaclass
# or
from future.utils import with_metaclass
class Boo(with_metaclass(BooType, object)):
pass

Using HTMLParser in Python 3.2

I have been using HTML Parser to scrapping data from websites and stripping html coding whilst doing so. I'm aware of various modules such as Beautiful Soup, but decided to go down the path of not depending on "outside" modules. There is a code code supplied by Eloff: Strip HTML from strings in Python
from HTMLParser import HTMLParser
class MLStripper(HTMLParser):
def __init__(self):
self.reset()
self.fed = []
def handle_data(self, d):
self.fed.append(d)
def get_data(self):
return ''.join(self.fed)
def strip_tags(html):
s = MLStripper()
s.feed(html)
return s.get_data()
It works in Python 3.1. However, I recently upgraded to Python 3.2.x and have found I get errors regarding the HTML Parser code as written above.
My first error points to the line:
s.feed(html)
... and the error says ...
AttributeError: 'MLStripper' object has no attribute 'strict'
So, after a bit of research, I add "strict=True" to the top line, making it...
class MLStripper(HTMLParser, strict=True)
However, I get the new error of:
TypeError: type() takes 1 or 3 arguments
To see what would happen, I removed the "self" argument and left in the "strict=True"... which gave up the error:
NameError: global name 'self' is not defined
... and I got the "I'm guessing on guesses" feeling.
I have no idea what the third argument in the class MLStripper(HTMLParser) line would be, after self and strict=True; research didn't toss any enlightenment.
You're subclassing HTMLParser, but you aren't calling its __init__ method. You need to add one line to your __init__ method:
def __init__(self):
super().__init__()
self.reset()
self.fed = []
Also, for Python 3, the import line is:
from html.parser import HTMLParser
With these changes, a simple example works. Don't change the class line, that's not related.

Resources