Using variables in __init__ method in Python - python-3.x

I have been given a Python module where I have a class named 'Node'. The __init__ method inside the class is given below:
def __init__(self, data = None, next = None):
self.fata = data
self._next = next
I want to know how this would differ if I simply mention data and next as variables and don't assign them to None? Like this:
def __init__(self, data, next):
self.fata = data
self._next = next

If
class A:
def __init__(self, data = None, next = None):
self._data = data
self._next = next
class B:
def __init__(self, data, next):
self._data = data
self._next = next
Then, e.g.:
>>> x = A(1,2)
>>> y = B(1,2)
>>> #no difference so far, but
>>> z = A()
>>> w = B()
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
w = B()
TypeError: __init__() missing 2 required positional arguments: 'data' and 'next'
Missing required arguments are a run-time error. They don't default to None.

Related

python __setattr__ causes attribute error on a defined variable

Every time the 'setattr' magic method is called it causes an attribute error for some reason. I'm getting an attribute error saying the 'rect' variable doesn't exist but it's clearly defined in the class.
import pygame as pg
class Block:
blocks = {}
id_ = 1
def __init__(self, surface, name=None, color=[0] * 3, width=0):
self.surface = surface
self.name = (name if name else Block.id_)
self.color = color
self.width = width
self.rect = pg.Rect((0, 0), [20] * 2)
self.block = self.make_block()
pg.draw.polygon(*self.block)
Block.blocks[self.name] = self
if not name:
Block.id_ += 1
def make_block(self):
point_1 = self.rect.topleft
point_2 = (self.rect.topleft[0], self.rect.topleft[1] + self.rect.size[1])
point_3 = (point_2[0] + self.rect.size[0], point_2[1])
point_4 = (point_3[0], point_1[0])
return [self.surface, self.color, (point_1, point_2, point_3, point_4), self.width]
def __setattr__(self, name, value):
pass
Block(pg.Surface((20, 20)))
You overrode __setattr__ to do nothing. That is where the attribute would be set. Take this small example:
In [3]: class Rect:
...: def __init__(self):
...: self.length = 12
...: self.width = 5
...: def __setattr__(self, name, val):
...: print(f"attempting to set {name}={val}")
...:
In [4]: r=Rect()
attempting to set length=12
attempting to set width=5
In [5]: r.length
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-5-1697af2cfc88> in <module>
----> 1 r.length
AttributeError: 'Rect' object has no attribute 'length'
Because I override it and don't actually set it, there's no attributes being set for my class. So when I try to access it, it will cause an error. I'm guessing that is what you're experiencing. If you want to fix that then you need to set the attribute when you override it and not just pass.

How to code my own dot product using a Python class?

I want to create a subclass of numpy adding a new method. Here is my first step:
class MyNumpy(np.ndarray):
def __init__(self):
np.ndarray.__init__(self)
def my_inner(self, x, y):
dotpr = 2*x[0]*y[0] + 3*x[1]*y[1]
return dotpr
Obviously my_inner() is wrong, but I wrote it here to show what I want.
Commenting out my_inner(), and typing in
p = MyNumpy([0.1, 0.2])
print("type(p): ", type(p))
p
the error message is produced
TypeError Traceback (most recent call last)
<ipython-input-54-2cee31ae802a> in <module>
----> 1 p = MyNumpy([0.1, 0.2])
2 print("type(p): ", type(p))
3 p
TypeError: 'float' object cannot be interpreted as an integer
I don't know what this 'float' object refers to here. Any help?
Thanks!
As #Quang Hoang pointed out, when you initiate the np.ndarray you pass it a shape, and it should be of type int, like:
class MyNumpy(np.ndarray):
def __init__(self, shape):
super().__init__()
def my_inner(self, x, y):
dotpr = 2*x[0]*y[0] + 3*x[1]*y[1]
return dotpr
p = MyNumpy((2, 6))
print("type(p): ", type(p))
p
cheers.

Getting unexpected NoneType error in Python

While trying to create a minimal, reproducible example for another problem in Python 3.7.3, I ran into a NoneType Error that I wasn't expecting.
Main program:
import worker
def multiply_worker_value(arguments):
current_Worker = arguments[0]
multiplier = arguments[1]
new_worker = current_Worker.change_value(multiplier)
return new_worker
current_worker = worker.Worker()
print("Printing value:")
print(current_worker.get_value()[0])
while(current_worker.get_value()[0] < 10):
paramList = [current_worker,2]
current_worker = multiply_worker_value(paramList)
print(current_worker.get_value()[0])
Worker class:
import numpy
class Worker():
def __init__(self):
self.values = numpy.random.rand(10)
def change_value(self,multiplier):
self.values = numpy.sum(self.values*multiplier)
def get_value(self):
return self.values
When this is run, I get:
Printing value:
0.10619190084595542
Traceback (most recent call last):
File "F:\Visual Studio\repos\Projects2020\tests\concurrent_test\concurrent_test\main.py", line 14, in <module>
while(current_worker.get_value()[0] < 10):
AttributeError: 'NoneType' object has no attribute 'get_value'
Press any key to continue . . .
and I am not sure why this is happening.
Inside the while loop, your current_worker gets overwritten with None:
current_worker = multiply_worker_value(paramList)
this calls:
new_worker = current_Worker.change_value(multiplier)
Your Worker.change_value method does not have a return statement, so it implicitly returns None.
Then, in the second iteration of your loop, your code tries to call get_value on None, which fails.

How to build a class-based decorator of a class in Python?

class Taggable:
TAG_ATTR_NAME = "_taggable_tag"
#staticmethod
def GetTag(target) -> str:
if not hasattr(target,Taggable.TAG_ATTR_NAME):
raise Exception(f"Object is not tagged")
return getattr(target,Taggable.TAG_ATTR_NAME)
def __init__(self, tag :str = "default_tag"):
self.tag = tag
def __call__(self,cls :type):
orig_new = cls.__new__
def my_new():
instance = orig_new(cls)
setattr(instance, Taggable.TAG_ATTR_NAME, self.tag)
return instance
if not isinstance(cls,type):
raise Exception(f"Decorator {type(self).__name__} applied to value {repr(cls)} of type {type(cls).__name__}")
cls.__new__ = my_new()
return cls
#Taggable
class A:
def __init__(self,fa :str):
self.fa = fa
print(f"__init__ called on A with fa={self.fa}, tagged as {Taggable.GetTag(self)}")
class B(A):
def __init__(self, fa: str, fb: str):
super().__init__(fa)
self.fb = fb
print(f"__init__ called on B with fb={self.fb}")
b: B = B("aaa","bbb")
print(Taggable.GetTag(b))
Running this on python 3.6 gives me the following error:
Traceback (most recent call last):
File "/Users/$user/Library/Preferences/PyCharmCE2019.1/scratches/scratch.py", line 35, in <module>
class B(A):
TypeError: __init__() takes from 1 to 2 positional arguments but 4 were given
Looking around the web there seems to be little to no authoritative documentation on how class decorator classes are initialized and called by the interpreter and what arguments are passed to their dunder methods

AttributeError when monkey patching an object in python

I tried to monkey patch an object in Python.
class C:
def __init__(self):
self.__n = 0
def f(self):
self.__n += 1
def __str__(self):
return str(self.__n)
c = C()
def up(self):
self.__n += 2
import types
c.up = types.MethodType(up, c)
c.up()
But I got an AttributeError
Traceback (most recent call last):
File "untitled4.py", line 19, in <module>
c.up()
File "untitled4.py", line 15, in up
self.__n += 2
AttributeError: 'C' object has no attribute '__n'
How can I fix the error?
As your up function isn't declared inside a class, it is not possible to apply name mangling rules to its locals, while it is applied for the attribute name. Therefore you'd need to apply the name mangling manually in your function:
def up(self):
self._C__n += 2

Resources