Pytest fails with AttributeError: 'str' object has no attribute 'x' - python

I am having trouble getting a test to pass. When I run the code it seems to work find, but in pytest it fails:
desk.py
class Dimension:
x = 0
y = 0
z = 0
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
class Desk:
def __init__(self, dimension):
self.dimension = dimension
#property
def dimension(self):
return self.__dimension
#dimension.setter
def dimension(self, d):
s = d.split(".")
self.__dimension = Dimension(int(s[0]), int(s[1]), int(s[2]))
#property
def is_large(self):
if self.dimension.x > 100:
return True
return False
test_desk.py
...
def test_is_large():
desk = Desk("5.5.5")
assert desk.is_large == False
...
I get AttributeError: 'str' object has no attribute 'x'
If I change to getter and setter methods it works find, but I would like to use decorators.
UPDATE:
I used python3 -m pytest to run pytest using python3 and it works fine

It's the double underscore of self.__dimension. Read this: What is the difference in python attributes with underscore in front and back
And this: How to access "__" (double underscore) variables in methods added to a class
Change self.__dimension to self._dimension and it will make.
EDIT: Not the underscore. Your code works perfectly in Python3. In Python2 I made it work this way:
class Dimension:
x = 0
y = 0
z = 0
def __init__(self, x, y, z):
self.x = 0
self.y = 0
self.z = 0
class Desk:
def __init__(self, dimension):
s = dimension.split(".")
self.__dimension = Dimension(int(s[0]), int(s[1]), int(s[2]))
#property
def dimension(self):
return self.__dimension
#dimension.setter
def dimension(self, d):
s = d.split(".")
self.__dimension = Dimension(int(s[0]), int(s[1]), int(s[2]))
#property
def is_large(self):
if self.dimension.x > 100:
return True
return False

Related

Redefining methods through class inheritance in Python

I'm playing around with class inheritance and I'm wondering if its possible to change aspects of an inherited method in the child class without having to rewrite the whole thing?
For example:
class Parent:
def _init_(self, x):
self.x = x
def foo(self):
a = self.x
if a > 0:
forward = True
elif a < 0:
forward = False
return forward
class Child1(Parent):
def foo(self, y=None, bool=False):
if bool:
a = y
else:
a = self.x
super().foo()
class Child2(Parent):
pass
What I'm looking for is if I called Child1.foo it could reassign the variable a before running through
the method, as defined in the parent class. Where a is dependent on the y and bool arguments passed through the rewritten method in Child1:
print(Child1(2).foo(-2, True))
# => False
print(Child1(2).foo())
# => True
print(Child2(2).foo())
# => True
Is this possible, or would I just have to rewrite a new method for each class?
I think I understand your problem and I have some suggestions for how you can resolve this:
Using "private" methods
For example:
class Parent:
def __init__(self, x):
self.x = x
def _foo(self, a=None):
a = a if a else self.x * 2
if a > 10:
over = True
else:
over = False
return over
def foo(self):
return self._foo()
class Child1(Parent):
def foo(self, y=None, condition=False):
if condition:
a = y*2
else:
a = self.x*2
return self._foo(a)
class Child2(Parent):
pass
In this example, all child classes will inherit the _foo "private" function, where they may or may not receive a value of a.
Using abstract classes
There is another solution to this problem with abstract classes (here is an example of how to do this), where you forces the child class to implement the function foo:
Important
Remembering that in the case of abstract classes, if you do not define the function decorated with #abstractmethod, you will receive an error similar to this TypeError: Can't instantiate abstract class Child2 with abstract methods foo
Example:
Python 2.x
from abc import ABCMeta, abstractmethod
class Parent:
__metaclass__ = ABCMeta
def __init__(self, x):
self.x = x
def _foo(self, a=None):
a = a if a else self.x * 2
if a > 10:
over = True
else:
over = False
return over
#abc.abstractmethod
def foo(self):
pass
class Child1(Parent):
def foo(self, y=None, condition=False):
if condition:
a = y*2
else:
a = self.x*2
return self._foo(a)
class Child2(Parent):
def foo(self):
return self._foo()
Python 3.x
class Parent(metaclass=ABCMeta):
def __init__(self, x):
self.x = x
def _foo(self, a=None):
a = a if a else self.x * 2
if a > 10:
over = True
else:
over = False
return over
#abc.abstractmethod
def foo(self):
pass
class Child1(Parent):
def foo(self, y=None, condition=False):
if condition:
a = y*2
else:
a = self.x*2
return self._foo(a)
class Child2(Parent):
def foo(self):
return self._foo()
In both examples you will have the same result by running this:
print(Child1(2).foo(10, True)) // True
print(Child1(2).foo()) // False
print(Child2(2).foo()) // False

Python fuction stereotyped

Class A has functionA has if. And functionA is repeated by 100 time in out.
In this case, it looks non scene to caluculate if self.z.... each time in called by for in out.
Class A():
def __ini__(self, z)
self.z = z
def functionA(self, a):
if self.z == 1:
b = zFunc1 * a
elif self.z == 2:
b = zFunc2 * a
return b
def out(self):
for i in range(100):
print(self.functionA(i))
So I'm looking for the way to fix functionA in __ini__ like
Class A():
def __ini__(self, z):
self.z = z
functionA < = FIX by (self.z = 2)
"""
def functionA(self, a):
b = zFunc2 * a
reuturn b
"""
Is there solution?
Just make zFunc* another class attribute decided in __init__:
class A:
def __init__(self, z):
self.z = z
self.z_func = zFunc1 if z == 1 else zFunc2
def function_a(self, a):
return self.z_func * a
In fact, in this example you don't even need self.z as an attribute at all.

Python Classes using __init and __repr__ methods

Iam trying to create a class that should accept two arguments, x and y, and be represented by a string 'Point(x, y)' with appropriate values for x and y
class Point(object):
def __init__(self, x, y):
self.x = 0
self.y = 0
def __repr__(self):
return "Point(%s,%s)"%(self.x, self.y)
Error:
Point(0,0) is not of type 'string'
Failed validating 'type' in schema['items']:
{'type': 'string'}
On instance[0]:
Point(0,0)
"self.x" is the value of the instance of your class. So, if you set "self.x = 0", it means whenever you create an object for that class, the "x" value of that object will always be 0 instead of what you pass in the parameter.
"x" is the value of what you pass in the parameter.
self.x = x
self.y = y
Code:
class MyClass():
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return "Point(%s,%s)"%(self.x, self.y)
thiss = MyClass(0, 0)
print(thiss.__repr__())
thiss = MyClass(20, 20)
print(thiss.__repr__())
Output:
daudn$ python3 point.py
Point(20,20)
daudn$ python3 point.py
Point(0,0)
When declaring your init function, you initialized self.x and self.y to always be 0. If you look at the code I've posted, whatever number you pass to the class will become the values or Point.

Add non-lamda function to self of Python class

Adding lambda expression to self of a Python class is easy:
class Foo(object):
def __init__(self, x):
if x > 0:
self.eval = lambda x: x
else:
self.eval = lambda x: x**2
return
def compute(self, y):
return self.eval(y)
In my case, self.eval is somewhat more complex such that it doesn't fit into a one-line lambda. I need def. How can I assign self.eval with a defined function though?
For performance reasons, I would like to not store self.x = x and not move the if into compute.
You can define a function anywhere:
class Foo(object):
def __init__(self, x):
if x > 0:
def eval(y):
return y
else:
def eval(y):
return y**2
self.eval = eval
def compute(self, y):
return self.eval(y)
Python functions are first class objects. You can assign any function to a variable:
class Foo(object):
def __init__(self, x):
if x > 0:
self.eval = self.method1
else:
self.eval = self.method2
def method1(self, x):
return x
def method2(self, x):
return x * x
def compute(self, y):
return self.eval(y)
f1 = Foo(1)
print(f1.compute(10)) # 10 (method1)
f2 = Foo(-1)
print(f2.compute(10)) # 100 (method2)
At least in Python 3 it is trivial to add a method to an existing class. Just look at the following code:
>>> class A:
val = 2 # declare a class variable (will be the default value
>>> def func(self, x): # declare a function that will be added as a method
return self.val * x
>>> A.compute = func # add the compute method to class A
>>> a = A() # create an instance
>>> a.val # control the value of the member
2
>>> a.compute(3) # use the added method
6
>>> a.val=3 # change the value of the variable for the specific instance
>>> a.compute(4) # control that the new variable value is used
12

How to define attribution of attribution in python

I am trying to make an attribution of an attribution in python.
Is there a way to do so:
class Foo():
def __init__(self, x, y):
self.x = x
self.x.y = y
I have no idea how to do it, I checked for some examples. But I have not found any example similar.
Not exactly clear what you need you can do something like this (for example):
class Bar(object):
def __init__(self, y=None):
self.y = y
class Foo(object):
def __init__(self, x, y):
self.x = x
self.x.y = y
if __name__ == '__main__':
x = Bar()
y = 1
foo = Foo(x,y)

Categories