Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the most general python type to which I can add attributes?

I have a class Foo with a method isValid. Then I have a method bar() that receives a Foo object and whose behavior depends on whether it is valid or not.

For testing this, I wanted to pass some object to bar whose isValid method returns always False. For other reasons, I cannot create an object of Foo at the time of testing, so I needed an object to fake it. What I first thought of was creating the most general object and adding the attribute isValid to it, for using it as a Foo. But that didn't quite work:

>>> foo = object()
>>> foo.isValid = lambda : False
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'isValid'

I found out object doesn't have a __dict__, so you cannot add attributes to it. At this point, the workaround I am using is creating a type on the fly for this purpose and then creating an object of that type:

>>> tmptype = type('tmptype', (), {'isValid' : lambda self : False})
>>> x = tmptype()
>>> x.isValid()
False

But this seems too long a shot. There must be some readily available general type that I could use for this purpose, but which?

like image 422
ricab Avatar asked Oct 14 '10 13:10

ricab


People also ask

How many attributes are there in Python?

Introduction. A Python object has two types of attributes: Class Attribute and Instance Attribute.

What are the attributes in Python?

To give a basic definition of both terms, class attributes are class variables that are inherited by every object of a class. The value of class attributes remain the same for every new object. Like you will see in the examples in this section, class attributes are defined outside the __init__() function.

How do I add an attribute to a class in Python?

Adding attributes to a Python class is very straight forward, you just use the '. ' operator after an instance of the class with whatever arbitrary name you want the attribute to be called, followed by its value.


3 Answers

you have the right idea but you can make it more general. Either

 tmptype = type('tmptype', (object,) {})

or

 class tmptype(object):
     pass

Then you can just do

foo = tmptype()
foo.is_valid = lambda: False

like you wanted to do with object. This way, you can use the same class for all of your dynamic, monky-patching needs.

like image 186
aaronasterling Avatar answered Nov 05 '22 18:11

aaronasterling


Just so that the right answer is stated and people don't have to read all the comments: There is no such type. It has been proposed, discussed, and the idea has been rejected. Here is the link that aaronasterling posted on a comment, where more can be read: http://mail.python.org/pipermail/python-bugs-list/2007-January/036866.html

like image 26
ricab Avatar answered Nov 05 '22 17:11

ricab


why do you have to have to make it complex? i think the most simple way (and the 'standard' way) is to do

class FakeFoo(object):
    def is_valid():
        return False

besides, the use of lambda is not good in this context... take a look at this: http://python-history.blogspot.com/2009/04/origins-of-pythons-functional-features.html is by the BDFL

and so on...

like image 1
Ant Avatar answered Nov 05 '22 18:11

Ant