Calling print(self) under __str__ throws a RecursionError - python

I have defined a class called spam:
class spam():
def __str__(self):
print(self)
a = spam()
print(a)
The print statement in the end gives me the following error:
Traceback (most recent call last):
File "<pyshell#73>", line 1, in <module>
print(a)
File "<pyshell#51>", line 3, in __str__
print(self)
File "<pyshell#51>", line 3, in __str__
print(self)
File "<pyshell#51>", line 3, in __str__
print(self)
#same lines repeated several times
RecursionError: maximum recursion depth exceeded
What is going on here? What happens when I say print(self) under str(self)? What is causing the recursion?

print calls str on the non-string object to be able to print it, which calls your __str__ member method.
Here is your recursion.
You define a __str__ method when you are able to convert your object to an "equivalent" string. If not, just leave the default (which prints the object type & address)
Note that __str__ should return something, not print. If you have some representative attribute, you could use it to return something interesting.
class spam():
def __init__(self,value):
self.__value = value
def __str__(self):
return "object '{}' with value {}".format(self.__class__.__name__, self.__value)
a = spam(10)
print(a)
prints:
object 'spam' with value 10

Related

override __getattr__ for methods and not variables

i want the next code to work
class A(object):
def __getattr__(self, item):
print item
return self.item
def x(self):
print 4
a = A()
a.x()
and the output will ber
x
4
i know its not working becuase x is like a static variable and not an instance variable.
I saw this __getattr__ for static/class variables in python and it doesn't seem to work in my case
how can it be done?
thx
There are a couple of obvious problems with your code:
class A(object):
def __getattr__(self, item): # 1
print item
return self.item # 2
def x(self): # 1 again
print 4
__getattr__ will only be invoked if item cannot be found the normal way. For item == 'x', therefore, it is never invoked.
Which is probably just as well, since self.item looks for the attribute item, not the attribute corresponding to whatever is assigned to item. This doesn't exist, so would invoke __getattr__. If you try A().y() you'll get RuntimeError: maximum recursion depth exceeded while calling a Python object.
Instead, I think you want to use __getattribute__, which is always invoked. You need to be careful not to get the same runtime error, though; here I avoid it by calling the superclass implementation of __getattribute__, the naïve way of calling getattr(self, item) would fail:
class A(object):
def __getattribute__(self, item):
print item
return super(A, self).__getattribute__(item)
def x(self):
print 4
Which gives:
>>> A().x()
x
4
>>> A().y()
y
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __getattribute__
AttributeError: 'A' object has no attribute 'y'
Note that both __getattr__ and __getattribute__ apply equally to attributes and methods (which are, more or less, just callable attributes).

TypeError: 'int' object is not callable- Sorry if AP

class Car:
# constructor
def __init__(self, make, model, year, mpg):
# instance variables
self.carMake = make
self.carModel=model
self.carYear = year
self.efficiency=mpg
self.gas = 0
# special method
def __str__(self):
return "%s %s %s"%(self.carYear, self.carMake, self.carModel)
def refuel(self,gallon):
if gallon < 0:
print("Sorry, amount cannot be negative")
else:
self.gas=self.gas+gallon
print (self.gas)
print("Added %.2f gallon of gas to the tank"%(self.gas))
def gas(self):
print(self.gas)
> Traceback (most recent call last): File "<pyshell#12>", line 1, in
> <module>
> c1.gas() TypeError: 'int' object is not callable
Your method gas and your instance attribute gas created in __init__ have the same name. The method is stored on the class, but is "shadowed" by the attribute stored on the instance, since Python first looks for names on the instance, then on the class and its parents.
So self.gas is an integer and you can't call it.
You have self.gas initialized to an int in the __init__() method, but then you define a method named gas() as well. Once __init__() runs, self.gas is an int. I'm guessing somewhere you are calling gas() on an instance of this class.
Rename your gas() method to something like print_gas(), or, wherever you're calling this, instead of doing c1.gas(), just do print c1.gas.
Consider this class Test in a file called test.py:
class Test:
def __init__(self):
self.x=3
def x(self):
print self.x
Now I import class Test in my console and see what methods it has:
>>> from test import Test
>>> [method for method in dir(Test) if callable(getattr(Test, method))]
['__init__', 'x']
Notice that it has the method x. Now let's create an instance of Test
>>> k=Test()
Let's see what methods we have
>>> [method for method in dir(k) if callable(getattr(k, method))]
['__init__']
>>>
As you can see the method x is no longer available. why?
When you created k as an instance of Test, it executes the __init__ method and sees self.x=3 which redefines x to be just a variable in self and your method x() is gone. So when you do k.x() it thinks that you are doing it on self.x that you set in __init__ which is not callable. However just k.x will work as I show below:
>>> k.x()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
>>> k.x
3
>>>
The conclusion is don't name your variables and methods the same.

python: unexplainable infinite recursion with __repr__

Here's a piece of code, which goes into an infinite recursion loop, which consists only of __repr__ function, seemingly calling itself. But I really can't see, how it calls itself. Moreover, I can't even understand, how it was called:
class MyList(list): #this is storage for MyDict objects
def __init__(self):
super(MyList, self).__init__()
class MyDict(dict):
def __init__(self, mylist):
self.mylist = mylist #mydict remembers mylist, to which it belongs
def __hash__(self):
return id(self)
def __eq__(self, other):
return self is other
def __repr__(self):
return str(self.mylist.index(self)) #!!!this is the crazy repr, going into recursion
def __str__(self):
return str(self.__repr__())
mylist = MyList()
mydict = MyDict(mylist)
mydict.update({1:2})
print str(mylist.index(mydict)) #here we die :(
Execution of this code results in:
Traceback (most recent call last):
File "test_analogue.py", line 20, in <module>
print str(mylist.index(mydict))
File "test_analogue.py", line 13, in __repr__
return str(self.mylist.index(self))
File "test_analogue.py", line 13, in __repr__
...
... (repetition of last 2 lines for ~666 times)
...
File "test_analogue.py", line 13, in __repr__
return str(self.mylist.index(self))
RuntimeError: maximum recursion depth exceeded while calling a Python object
Do you understand, how str(mylist.index(mydict)) managed to call __repr__? I'm completely puzzled. Thanks!
>> mylist.index('foo')
ValueError: 'foo' is not in list
You never actually added mydict to mylist, so the index method tries to raise this error. The error contains the repr of the dict. The repr of the dict, of course, tries to look up its index in the list that it isn't in, and this raises an exception, whose error message is calculated using the repr of the dict, which of course, tries to look up its index in the list that it isn't in, and...

exec to add a function into a class

So I've looked at similar questions, and I've found some solutions to this, but I can't quite figure out how to do this.
What I'm trying to do is add a method to a class from a string. I can do this with the setattr() method, but that won't let me use self as an attribute in the extra method. Here's an example: (and I apologize for the variable names, I always use yolo when I'm mocking up an idea)
class what:
def __init__(self):
s = 'def yolo(self):\n\tself.extra = "Hello"\n\tprint self.extra'
exec(s)
setattr(self,"yolo",yolo)
what().yolo()
returns this:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: yolo() takes exactly 1 argument (0 given)
and if s = 'def yolo():\n\tself.extra = "Hello"\n\tprint self.extra'
then I get this result:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 2, in yolo
NameError: global name 'self' is not defined
This essentially means that I cannot dynamically create methods for classes, which I know is bad practice and unpythonic, because the methods would be unable to access the variables that the rest of the class has access to.
I appreciate any help.
You have to bind your function to the class instance to turn it into a method. It can be done by wrapping it in types.MethodType:
import types
class what:
def __init__(self):
s = 'def yolo(self):\n\tself.extra = "Hello"\n\tprint self.extra'
exec(s)
self.yolo = types.MethodType(yolo, self)
what().yolo()
On a side note, why do you even need exec in this case? You can just as well write
import types
class what:
def __init__(self):
def yolo(self):
self.extra = "Hello"
print self.extra
self.yolo = types.MethodType(yolo, self)
what().yolo()
Edit: for the sake of completeness, one might prefer a solution through the descriptor protocol:
class what:
def __init__(self):
def yolo(self):
self.extra = "Hello"
print self.extra
self.yolo = yolo.__get__(self)
what().yolo()
Another way, seems more elegant to me:
class what:
pass
ld = {}
exec("""
def yolo(self):
self.extra = "Hello"
print(self.extra)
""", None, ld)
# print('locals got: {}'.format(ld))
for name, value in ld.items():
setattr(what, name, value)
what().yolo()

How to handle & return both properties AND functions missing in a Python class using the __getattr__ function?

It is fairly easy to use the __getattr__ special method on Python classes to handle either missing properties or functions, but seemingly not both at the same time.
Consider this example which handles any property requested which is not defined explicitly elsewhere in the class...
class Props:
def __getattr__(self, attr):
return 'some_new_value'
>>> p = Props()
>>> p.prop # Property get handled
'some_new_value'
>>> p.func('an_arg', kw='keyword') # Function call NOT handled
Traceback (most recent call last):
File "<console>", line 1, in <module>
TypeError: 'str' object is not callable
Next, consider this example which handles any function call not defined explicitly elsewhere in the class...
class Funcs:
def __getattr__(self, attr):
def fn(*args, **kwargs):
# Do something with the function name and any passed arguments or keywords
print attr
print args
print kwargs
return
return fn
>>> f = Funcs()
>>> f.prop # Property get NOT handled
<function fn at 0x10df23b90>
>>> f.func('an_arg', kw='keyword') # Function call handled
func
('an_arg',)
{'kw': 'keyword'}
The question is how to handle both types of missing attributes in the same __getattr__? How to detect if the attribute requested was in property notation or in method notation with parentheses and return either a value or a function respectively? Essentially I want to handle SOME missing property attributes AND SOME missing function attributes and then resort to default behavior for all the other cases.
Advice?
How to detect if the attribute requested was in property notation or in method notation with parentheses and return either a value or a function respectively?
You can't. You also can't tell whether a requested method is an instance, class, or static method, etc. All you can tell is that someone is trying to retrieve an attribute for read access. Nothing else is passed into the getattribute machinery, so nothing else is available to your code.
So, you need some out-of-band way to know whether to create a function or some other kind of value. This is actually pretty common—you may actually be proxying for some other object that does have a value/function distinction (think of ctypes or PyObjC), or you may have a naming convention, etc.
However, you could always return an object that can be used either way. For example, if your "default behavior" is to return attributes are integers, or functions that return an integer, you can return something like this:
class Integerizer(object):
def __init__(self, value):
self.value = value
def __int__(self):
return self.value
def __call__(self, *args, **kw):
return self.value
There is no way to detect how the returned attribute was intended to be used. Everything on python objects are attributes, including the methods:
>>> class Foo(object):
... def bar(self): print 'bar called'
... spam='eggs'
...
>>> Foo.bar
<unbound method Foo.bar>
>>> Foo.spam
'eggs'
Python first looks up the attribute (bar or spam), and if you meant to call it (added parenthesis) then Python invokes the callable after lookup up the attribute:
>>> foo = Foo()
>>> fbar = foo.bar
>>> fbar()
'bar called'
In the above code I separated the lookup of bar from calling bar.
Since there is no distinction, you cannot detect in __getattr__ what the returned attribute will be used for.
__getattr__ is called whenever normal attribute access fails; in the following example monty is defined on the class, so __getattr__ is not called; it is only called for bar.eric and bar.john:
>>> class Bar(object):
... monty = 'python'
... def __getattr__(self, name):
... print 'Attribute access for {0}'.format(name)
... if name == 'eric':
... return 'idle'
... raise AttributeError(name)
...
>>> bar = Bar()
>>> bar.monty
'python'
>>> bar.eric
Attribute access for eric
'idle'
>>> bar.john
Attribute access for john
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in __getattr__
AttributeError: john
Note that functions are not the only objects that you can invoke (call); any custom class that implements the __call__ method will do:
>>> class Baz(object):
... def __call__(self, name):
... print 'Baz sez: "Hello {0}!"'.format(name)
...
>>> baz = Baz()
>>> baz('John Cleese')
Baz sez: "Hello John Cleese!"
You could use that return objects from __getattr__ that can both be called and used as a value in different contexts.

Categories