I try to use the composition relationship but I can't access to the compound class A:
with this code I'm trying to add to the list of class A, an object from the class B.
class B:
def __init__(self,X,Y,Z):
self.X
self.Y
self.Z
def Xreturner(self):
return self.X
def Yreturner(self):
return self.Y
def Zreturner(self):
return self.Z
class A:
def __init(self):
self.lst=[[1,2,3],[3,4,5],]
self.b=B()
def add(self): # trying to add b object to the list
self.lst.append(self.b)
#### TEST####
objA=A()
objA.add(6,7,8)
When I test I get this error:
Traceback (most recent call last):
File "home/testXYZ.py", line 28, in <module>
objA.add(6,7,8)
TypeError: add() takes exactly 1 argument (4 given)
Please help me to solve this.
The statement self.X in the __init__ method of B does nothing. You need to put self.X = X.
You are passing parameters to add() but it doesn't take any parameters. Maybe you want to add parameters (in the same way you have some for __init__ of X.
Maybe you even want to pass parameters to the __init__ of A (instead of to A). Then you can pass those to the constructor of B.
First, your class B initializer is incorrect:
class B:
def __init__(self, x, y, z): # <== should use snake_case for vars
self.x = x
self.y = y
self.z = z
Next, your class A add should create a new B object and add to the list:
def add(self, x, y, z):
new_b = B(x, y z)
self.lst.append(new_b)
Related
I need to understand these things in python here are some codes. I want a nice description of it.
When I used the first code, "self" was necessary, When I used the second code "self" gave me an error. How?
class Sample():
def example(self, x, y):
z = x+ y
return print(z)
x = Sample()
x.example(1,2)
class Sample():
def example(x, y):
z = x+ y
return print(z)
Sample.example(1,2)
and this code gives me an error, I don't know where I am wrong
class Sample():
def __init__(self, x, y):
self.x = x
self.y =y
def example(self):
z = self.x + self.y
return print(z)
x = Sample()
x.example(1,2)
Error
Traceback (most recent call last):
File "c:\Users\Lenovo\Documents\PP\Advance python\example.py", line 13, in <module>
x = Sample()
TypeError: __init__() missing 2 required positional arguments: 'x' and 'y'
Another code with error
def example(self):
z = self.x + self.y
return print(z)
example(1,2)
Error
Traceback (most recent call last):
File "c:\Users\Lenovo\Documents\PP\Advance python\example.py", line 8, in <module>
example(1,2)
TypeError: example() takes 1 positional argument but 2 were given
I would really appreciate the help.
The __init__ method is a constructor so it essentially initializes the attributes of the object. So you should pass the arguments when you are creating the object. When you use self that means those attribute/methods relates to the same class.
class Sample:
def __init__(self, x, y):
self.x = x
self.y = y
def example(self):
z = self.x + self.y
return print(z)
x_object = Sample(1, 2)
x_object.example()
So rather than passing the arguments to x.example you should pass them to Sample()
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.
When I initialize an instance of class B, shouldn't it raise an error for not attempting to supply a value for the x attribute in class A's init method? What if I want an error to be raised if x is not supplied a value?
Example:
class A:
def __init__(self, x):
self.x = x
class B(A):
def __init__(self, y):
self.y = y
z = B(4) #Shouldn't I be getting an error for not attempting to
#initialize x from the base class?
No.
What you are doing is initializing y, since in your init of B class, you are not calling your parents constructror
super.__init__()
If you wanted to use both x,y from B and having to initialize x from B, you should use this:
class A:
def __init__(self, x):
self.x = x
class B(A):
def __init__(self, x, y):
super().__init__(x)
self.y = y
Is it possible to only allow a user invoke any/all object methods when the object itself is called?
Looking for different examples on how to do this
Some example code
class Test:
def __init__(self, x=1):
self.x = x
def __call__(self, x=1):
self.x = x
return self
def get(self, y):
return (self.x * y)
t_obj = Test()
t_obj(2).get(1) # Acceptable case
t_obj.get(1) # Raises exception
t_obj().get(2) # Acceptable case
Right way to do it
It seems to me that what you want is for t_obj to actually be the class and not an instance of Test. It then gives the exact behavior you showed in your example.
class Test:
def __init__(self, x=1):
self.x = x
def get(self, y):
return (self.x * y)
t_obj = Test # not an object, actually a class
t_obj(2).get(1) # 2
t_obj.get(1) # Raises exception
t_obj().get(2) # 2
In particular, the exception states that method get() must be called with Test instance, i.e. you had to call t_obj to instantiate an object before being able to call get(), which is exactly what you want.
Fun way to do it
Although, suppose you really need your objects to be callable, here is a hacky way to get this working. It replaces the get method of your object when called, replacing a placeholder which only purpose is to raise.
class Test:
def __init__(self, x=1):
self.x = x
def __call__(self, x):
self.x = x
self.get = lambda y: self.x * y
return self
def get(self, y):
raise AttributeError('call object first')
t_obj = Test()
t_obj.get(1) # Raises exception
t_obj(2)
t_obj.get(1) # 2
Say I have a class definition which takes some arguments and creates additional data with it, all within the __init__ method:
class Foo():
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
self.bar = generate_bar(x, y, z)
def generate_bar(self, x, y, z):
return x+y+z
I only want to run the generate_bar() method once, when an instance of the class is created, so it wouldn't make sense for that method to be callable on the instance. Is there a sleeker way to ensure that a method is only available to __init__, or do I just have to assume anyone who looks at my code will understand that there's never a situation in which it would be appropriate to call generate_bar() on an instance of the class?
If you are not using any instance state, just make it a separate function:
def _generate_bar(x, y, z):
return x + y + z
class Foo():
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
self.bar = _generate_bar(x, y, z)
The leading underscore, by convention, signals it is an internal function not to be used by external consumers of your module.
You could nest the function inside the __init__ but this doesn't really help with readability:
class Foo():
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def generate_bar():
return x + y + z
self.bar = generate_bar()
Here generate_bar() doesn't even need arguments, it could access x, y and z from the enclosing scope.
For "hidden" functions, it is customary to use a single underscore to signify your intent:
def _generate_bar(self, x, y, z): ...
These are still accessible, but are not visible via tab completion.
See this SO explanation:
class foo:
def __init__(self):
self.response = self._bar()
def _bar(self):
return "bar"
f = foo()
>>> f.response
bar
You can verify yourself that the function _bar is not visible to the object via tab completion