I am using a object as key and number as value but getting the below error in line. Any help ?
dict[a] = 1
:
Traceback (most recent call last):
File "detect_hung_connections.py", line 24, in <module>
dict = {a:1}
TypeError: __hash__() takes exactly 3 arguments (1 given)
My Code is as follows:
class A:
def __init__(self,a,b):
self.a = a
self.b = b
def __hash__(self,a,b):
return hash(self.a,self.b)
def __eq__(self,other):
return (self.a,self.b) == (other.a,other.b)
dict ={}
a = A("aa","bb")
dict[a] = 1
b = A("aa","bb")
The signature of A.__hash__ should not take any extra arguments.
def __hash__(self):
return hash((self.a,self.b))
You're calling hash with the entire object and (redundantly) its two attributes. You can use only a single value to hash. Try this, perhaps:
def __hash__(self):
return hash(self.a + self.b)
This at least passes execution.
Related
I have a class with several methods. Outputs of a method are used in other methods. I don't want to pass these variables as input argument to other methods (to make code more simple).
I can add output of this method into self so I have access to these variables in other methods.
But, I want to be sure that it is a standard implementation. I am worried that it may cause unpredictable error. If you have experience in this regard, please let me know if the following example is a correct implementation or not.
class MyClass:
def method_1(self, A):
return A + 1
def method_2(self):
return self.B + 10
def method_3(self, C):
self.B = self.method_1(C)
result = self.method_2()
return result
z = MyClass()
z.method_3(1)
In the above example, I don't need to pass self.B into method_2. This code works but I want to be sure that it is a standard way.
The real program I working on is complicated, so I made a simple example for this question.
Yup it is more or less correct but the standard way of doing something like this is having a __init__() method and using function annotations.
class MyClass:
def __init__(self) -> None:
self.B = 0
def method_1(self, A: int) -> int:
return A + 1
def method_2(self) -> int:
return self.B + 10
def method_3(self, C: int) -> int:
self.B = self.method_1(C)
result = self.method_2()
return result
z = MyClass()
z.method_3(1)
Where method_2() relies on an attribute that may be unset, make it private so that people aren't tempted to use it. For example, what if I did this?
>>> z = MyClass()
>>> z.method_2()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "tmp.py", line 9, in method_2
return self.B + 10
AttributeError: 'MyClass' object has no attribute 'B'
For that matter, it's probably best to make the attribute private too. So:
class MyClass:
def method_1(self, A):
return A + 1
def _method_2(self):
return self._B + 10
def method_3(self, C):
self._B = self.method_1(C)
result = self._method_2()
return result
By the way, where method_1() doesn't use self, consider making it a staticmethod.
I'm implementing the decorator described in What is the Python equivalent of static variables inside a function?. In the answer, the decorator is put on a normal function and it worked also in my environment.
Now I'd like to put the decorator onto a class method.
Source Code:
#decorator
def static_variabls(**kwargs):
def new_func(old_func):
for key in kwargs:
setattr(old_func, key, kwargs[key])
return old_func
return new_func
class C:
#static_variabls(counter = 1)
def f_(self) -> None:
print(self.f_.counter)
self.f_.counter += 1
c1 = C()
c1.f_()
c1.f_()
c1.f_()
Expected Result:
1
2
3
Actual Result:
1
Traceback (most recent call last):
File "1.py", line 16, in <module>
c1.f_()
File "1.py", line 13, in f_
self.f_.counter += 1
AttributeError: 'method' object has no attribute 'counter'
I don't understand why this code doesn't work. According to the error message, self.f_.counter doesn't exist but print(self.f_.counter) works. What's happening here?
c1.f_() is equivalent to C.f_.__get__(c1, C)() (due to the descriptor protocol). __get__ returns the method object that actually gets called. You attached counter to the original function object, which isn't what the method wraps: it wraps the function created by def new_func.
Note that you have the same problem with a much simpler decorator, that hard-codes the attribute and its initial value.
def add_counter(f):
f.counter = 1
return f
class C:
#add_counter
def f_(self) -> None:
print(self.f_.counter)
self.f_.counter += 1
or even with no decorator:
class C:
def f_(self) -> None:
print(self.f_.counter)
self.f_.counter += 1
f_.counter = 1
You can't define/use, variable, function or an objects, as a static member, and then use self to access them.
In case of self.f_.counter, I guess print() function works, as, it tries to access memory address (of the class itself) directly, in your code f_.counter, not binded with self address., it's binded with ,C.f_ adderss itself.
Solution - 1
def static_variabls(**kwargs):
def new_func(old_func):
for key in kwargs:
setattr(old_func, key, kwargs[key])
return old_func
return new_func
class C:
#static_variabls(counter = 1)
def f_(self) -> None:
print(C.f_.counter) # OR self.f_.counter
C.f_.counter += 1
Solution - 2 (Without using decorators)
class C:
counter = 0 # static variable
def __init__(self):
C.counter += 1
print(self.counter)
c1 = C()
c1 = C()
c1 = C()
I am trying to create a custom python shell where I initialize some objects on startup. Those objects could be individual items or list. the user of the shell could then call methods from those objects to perform some functions:
For Ex, this code is run on the start of the python shell:
# Init the objects on startup of shell
if NeedObjList:
a = [ObjClass(x,y,z) ObjClass(p,q,r)]
else:
a = ObjClass(x, y, z)
Now in the shell, user will have to know that the initialized variable 'a' is a list or a class object. There can be a message displayed on startup of the python shell. But in case it is not seen, user might try to access the variable as a list when it was an object and vice versa.
I was wondering if the list itself can be created as a smart list. i.e. if the user supplies an index to the list, the object at the index is returned. Otherwise in case of an invalid index or no index being given, the list returns the 0th element (or any fixed element for that matter)
An example of the use case:
class example:
def __init__(self):
self.a=1
self.b=2
def cl_print(self):
print "works : {0} {1}".format(self.a, self.b)
if NeedObjList:
a = [example() example()]
else:
a = example()
Now in the shell, this file is imported on start (using "python -i"):
Case 1: Object list was created
>>>a[0].cl_print()
works : 1 2
>>> a.cl_print() # will fail
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute 'cl_print'
Case 2: Object was created
>>> a.cl_print()
works : 1 2
>>> a[0].cl_print()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: hello instance has no attribute '__getitem__'
I wanted to try and see if I could make things work for user without them having to do a try-except.
Making __getitem__() return the instance:
class Example(object):
def __init__(self):
self.a=1
self.b=2
def cl_print(self):
print("works : {0} {1}".format(self.a, self.b))
def __getitem__(self, item):
return self
and delegating attribute lookup of not found attributes to
the first list member with __getattr__() would work:
class MyList(list):
def __getattr__(self, attr):
return getattr(self[0], attr)
With a list:
>>> a = MyList([Example(), Example()])
>>> a.cl_print()
works : 1 2
>>> a[0].cl_print()
works : 1 2
With an instance:
>>> a = Example()
>>> a.cl_print()
works : 1 2
>>> a[0].cl_print()
works : 1 2
You can implement __iter__, __len__, and __getitem__ on your ObjClass to make it act like a list of one item:
class ObjClass(object):
def __iter__(self):
yield self
def __len__(self):
return 1
def __getitem__(self, i):
if i == 0: return self
raise IndexError("list index out of range")
Use try ... except:
tokens=['aaaa', 'bbb', 'ccc', 'ddd', 'eee']
try:
a = tokens[N]
except IndexError:
a = tokens[0]
If N-th element exists in list, then it will be returned, otherwise 0 element (or some other) will be returned.
I have a class which instances shall be presented as string if being used in the context of a string. To be precise, a attribute pointing to a string should be returned.
The class looks as the following and works so far:
class Test:
string = ""
def __init__(self, value=""):
self.string = value
def __repr__(self):
return str(self.string)
def __str__(self):
return self.__repr__()
def __add__(self, other):
return "%s%s" % (self.string, other)
def __radd__(self, other):
return "%s%s" % (other, self.string)
Unfortunately, I get a TypeError when I try doing something like this:
>>> "-".join([Test("test"), Test("test2")])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: sequence item 0: expected string, instance found
Doing the same with a string, I get the expected result:
>>> "-".join(["test", "test"])
'test-test'
>>>
I'm pretty sure I'm just missing the correct operator overload function.
Could somebody how to achieve this with class instances in the list?
Thanks.
join requires elements to be strings, as documented here:
https://docs.python.org/3/library/stdtypes.html#str.join
You need to explicitly convert your objects to strings, e.g.:
"-".join(map(str, [Test("test"), Test("test2")]))
I have a method in my Customer class called save_from_row(). It looks like this:
#classmethod
def save_from_row(row):
c = Customer()
c.name = row.value('customer', 'name')
c.customer_number = row.value('customer', 'number')
c.social_security_number = row.value('customer', 'social_security_number')
c.phone = row.value('customer', 'phone')
c.save()
return c
When I try to run my script, I get this:
Traceback (most recent call last):
File "./import.py", line 16, in <module>
Customer.save_from_row(row)
TypeError: save_from_row() takes exactly 1 argument (2 given)
I don't understand the mismatch in the number of arguments. What's going on?
The first argument to a classmethod is the class itself. Try
#classmethod
def save_from_row(cls, row):
c = cls()
# ...
return c
or
#staticmethod
def save_from_row(row):
c = Customer()
# ...
return c
The classmethod variant will enable to create subclasses of Customer with the same factory function.
Instead of the staticmethod variant, I'd usually use module-level functions.
You want:
#classmethod
def save_from_row(cls, row):
Class methods get the method's class as the first argument.