I was Googling some Python-related questions earlier, and stumbled upon this page. The author does something like the following:
class TestClass(object):
first = str()
def __init__(self):
self.first = "Hello"
What's the point of "declaring" the variable first like that? I've never seen this done before, and I can't for the life of me think of a situation where it is beneficial to create a variable before assigning it some value.
The above example could just as well have looked like this:
class TestClass(object):
def __init__(self, first="Hello"):
self.first = first
...or am I missing something?
The fact that the author uses
first = str()
as opposed to
first = ''
shows, alongside setting self.first in __init__ anyway, that there that is no purpose in doing this.
Maybe the author is confused and thinks python variable need to be declared first -_- (evident when viewing the link)
That's not a declaration, that's an assignment ... to a variable inside the class, as opposed to a variable inside an instance.
Consider the following output:
>>> class K1(object):
... def __init__(self):
... self.attr = 'value'
...
>>> x = K1()
>>> x.__dict__
{'attr': 'value'}
>>> class K2(object):
... attr = 'value'
... def __init__(self):
... self.another = 'value2'
...
>>> y = K2()
>>> y.__dict__
{'another': 'value2'}
Here x is an instance of class K1 and has an attribute named attr, and y is an instance of class K2 and has a different attribute named another. But:
>>> y.attr
'value'
Where did that come from? It came from the class:
>>> y.__class__.__dict__
dict_proxy({'__module__': '__main__', 'attr': 'value',
'__dict__': <attribute '__dict__' of 'K2' objects>,
'__weakref__': <attribute '__weakref__' of 'K2' objects>,
'__doc__': None, '__init__': <function __init__ at 0x80185b9b0>})
That's kind of messy but you can see the attr sitting in there. If you look at x.__class__.__dict__ there's no attr:
>>> x.__class__.__dict__
dict_proxy({'__dict__': <attribute '__dict__' of 'K1' objects>,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'K1' objects>,
'__doc__': None, '__init__': <function __init__ at 0x80185b938>})
When you get an attribute on an instance, like x.attr or y.attr, Python first looks for something attached to the instance itself. If nothing is found, though, it "looks upward" to see if something else defines that attribute. For classes with inheritance, that involves going through the "member resolution order" list. In this case there is no inheritance to worry about, but the next step is to look at the class itself. Here, in K2, there's an attribute in the class named attr, so that's what y.attr produces.
You can change the class attribute to change what shows up in y.attr:
>>> K2.attr = 'newvalue'
>>> y.attr
'newvalue'
And in fact, if you make another instance of K2(), it too will pick up the new value:
>>> z = K2()
>>> z.attr
'newvalue'
Note that changing x's attr does not affect new instances of K1():
>>> w = K1()
>>> w.attr = 'private to w'
>>> w.attr
'private to w'
>>> x.attr
'value'
That's because w.attr is really w.__dict__['attr'], and x.attr is really x.__dict__['attr']. On the other hand, y.attr and z.attr are both really y.__class__.__dict__['attr'] and z.__class__.__dict__['attr'], and since y.__class__ and z.__class__ are both K2, changing K2.attr changes both.
(I'm not sure the guy who wrote the page referenced in the original question realizes all this, though. Creating a class-level attribute and then creating an instance-level one with the same name is kind of pointless.)
str() is equal to ""
>>> str()
''
I think the author wants to show that instance attributes override class attributes having same name. So on executing
test = testclass()
print test.__dict__
you'll get:
{'second': 'weird', 'third': 'test', 'first': 'Some'}
not
{'second': '', 'third': '', 'first': ''}
but
print testclass.__dict__
will print the class attributes:
{'__module__': '__main__', 'third': '', 'second': '', '__doc__': None, '__init__': <function __init__ at 0xb5fed6bc>, 'first': ''}
There is indeed a little difference between the two examples:
class TestClass(object):
first = 'foo'
def __init__(self):
self.first = "Hello"
print(TestClass.first)
Output:
foo
However with:
class TestClass(object):
def __init__(self, first="Hello"):
self.first = "Hello"
print(TestClass.first)
Output:
Traceback (most recent call last):
File "C:\Users\...\Desktop\test.py", line 5, in <module>
print(TestClass.first)
AttributeError: type object 'TestClass' has no attribute 'first'
Note: But that doesn't mean that the author's code make sense. Just wanted to point out the difference.
Related
I am trying to print a list of the methods that have not been inherited from other classes (e.g.., not inheritted from object or another base class). As an example say I have the following class:
class Point:
def __init__(self, x, y):
self.__x=x
self.__y=y
calling this method should print:
[__init__] without __str__ (inheritted from object).
I've tried:
dir(Point)
but the problem is that it includes already inheritted methods.
To print the non-inherited attributes of an object, such as a class object, use vars which checks the __dict__ of that object:
In [1]: class Point:
...: def __init__(self, x, y):
...: self.__x=x
...: self.__y=y
...:
In [2]: vars(Point)
Out[2]:
mappingproxy({'__dict__': <attribute '__dict__' of 'Point' objects>,
'__doc__': None,
'__init__': <function __main__.Point.__init__>,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'Point' objects>})
Since a method is merely a callable object in the class, you can check for it using something to the effect of:
In [3]: for k, v in vars(Point).items():
...: if callable(v):
...: print(k)
...:
__init__
You can look into the __dict__ of the class itself:
import types
def list_methods(t):
for name, item in t.__dict__.items():
if isinstance(item, types.FunctionType):
print(name)
t is a class object here, not an instance of a class. If you want to operate on instances, replace t.__dict__.items() with type(t).__dict__.items() in the loop.
Please consider the following python example:
In [3]: class test(object):
...: attribute='3'
...: def __init__(self):
...: self.other='4'
...:
In [4]: b=test()
In [5]: b.attribute
Out[5]: '3'
In [6]: b.__dict__
Out[6]: {'other': '4'}
Why is it that __dict__ only shows the "other" attribute and not "atribute"?
And how do I get a dictionary with all the classe's attributes and values? That is, how do I get this?
{'other': '4', 'attribute': '3'}
And I mean by using __dict__ or by some other simple means.
PS: related to this question, but couldn't quite get a dict from there.
PS2: I'm not look for test.__dict__ or b.__class__.__dict__, I'm looking for something that can be used as
In [3]: class test(object):
...: attribute='3'
...: def __init__(self):
...: self.other='4'
...: def _print_atr(self):
...: # This should print exactly {'other': '4', 'attribute': '3'}
...: print(self.__all_atr__)
In [4]: b=test()
In [5]: b.attribute
Out[5]: '3'
In [6]: b.__dict__
Out[6]: {'other': '4'}
Cheers
attribute is not an instance attribute but a class attribute (can be seen in the mappingproxy test.__dict__).
You can get attribute in the instance __dict__ if you update the value of attribute from the instance:
>>> b = test()
>>> b.__dict__
{'other': '4'}
>>> b.attribute
'3'
>>> b.attribute = 5
>>> b.__dict__
{'attribute': 5, 'other': '4'}
Or keep the original value with
>>> b.attribute = b.__class__.attribute # may not be necessary
Or you could change the definition of the class and move attribute into one of the class methods and bind it to the instance via self.
b.__dict__ is only a mapping of attributes on b, not on b's class (notice that __init__ isn't there either). The attributes on b's class are on the class's __dict__.
>>> class test(object):
... attribute = 1
... def __init__(self):
... self.other = 2
...
>>> b = test()
>>> b.__dict__
{'other': 2}
>>> test.__dict__
dict_proxy({'__module__': '__main__', 'attribute': 1, '__dict__': <attribute '__dict__' of 'test' objects>, '__weakref__': <attribute '__weakref__' of 'test' objects>, '__doc__': None, '__init__': <function __init__ at 0x1030f72a8>})
If you want both, you can do something like:
d = dict(vars(type(b)))
d.update(vars(b))
(note that some prefer vars(b) to b.__dict__) Of course, this doesn't get subclasses ...
If you want subclasses, you'll need to walk the method resolution order...
d = {}
for cls in type(b).__mro__:
d.update(vars(cls))
d.update(vars(b))
Try typing:
test.__dict__
And it shows a key with 'attribute'. This happens exactly because attribute is a class variable not an instance variable.
Is it possible to obtain a list of all #property decorated methods in a class? If so how?
Example:
class MyClass(object):
#property
def foo(self):
pass
#property
def bar(self):
pass
How would I obtain ['foo', 'bar'] from this class?
Anything decorated with property leaves a dedicated object in your class namespace. Look at the __dict__ of the class, or use the vars() function to obtain the same, and any value that is an instance of the property type is a match:
[name for name, value in vars(MyClass).items() if isinstance(value, property)]
Demo:
>>> class MyClass(object):
... #property
... def foo(self):
... pass
... #property
... def bar(self):
... pass
...
>>> vars(MyClass)
dict_proxy({'__module__': '__main__', 'bar': <property object at 0x1006620a8>, '__dict__': <attribute '__dict__' of 'MyClass' objects>, 'foo': <property object at 0x100662050>, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__doc__': None})
>>> [name for name, value in vars(MyClass).items() if isinstance(value, property)]
['bar', 'foo']
Note that this will include anything that used property() directly (which is what a decorator does, really), and that the order of the names is arbitrary (as dictionaries have no set order).
Say I have a class which defines __slots__:
class Foo(object):
__slots__ = ['x']
def __init__(self, x=1):
self.x = x
# will the following work?
def __setattr__(self, key, value):
if key == 'x':
object.__setattr__(self, name, -value) # Haha - let's set to minus x
Can I define __setattr__() for it?
Since Foo has no __dict__, what will it update?
All your code does, apart from negate the value, is call the parent class __setattr__, which is exactly what would happen without your __setattr__ method. So the short answer is: Sure you can define a __setattr__.
What you cannot do is redefine __setattr__ to use self.__dict__, because instances of a class with slots do not have a __dict__ attribute. But such instances do have a self.x attribute, it's contents are just not stored in a dictionary on the instance.
Instead, slot values are stored in the same location a __dict__ instance dictionary would otherwise be stored; on the object heap. Space is reserved for len(__slots__) references, and descriptors on the class access these references on your behalf.
So, in a __setattr__ hook, you can just call those descriptors directly instead:
def __setattr__(self, key, value):
if key == 'x':
Foo.__dict__[key].__set__(self, -value)
Interesting detour: yes, on classes without a __slots__ attribute, there is a descriptor that would give you access to the __dict__ object of instances:
>>> class Bar(object): pass
...
>>> Bar.__dict__['__dict__']
<attribute '__dict__' of 'Bar' objects>
>>> Bar.__dict__['__dict__'].__get__(Bar(), Bar)
{}
which is how normal instances can look up self.__dict__. Which makes you wonder where the Bar.__dict__ object is found. In Python, it is turtles all the way down, you'd look that object up on the type object of course:
>>> type.__dict__['__dict__']
<attribute '__dict__' of 'type' objects>
>>> type.__dict__['__dict__'].__get__(Bar, type)
dict_proxy({'__dict__': <attribute '__dict__' of 'Bar' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Bar' objects>, '__doc__': None})
Im adding callable objects to a instance of a class A at runtime using the __dict__ property. At some point though I want to remove all added objects from my instance. I thought about storing the initial __dict__ property in a member _orgDict and then execute self.__dict__ = self._orgDict later. Im wondering whether:
This works at all?
The removed objects are really deleted or just not contained in my instance anymore?
You mean the del statement?
del(instance.attribute)
A quick test shows that reassigning an instance __dict__ seems to work:
>>> class B(object):
pass
>>> b = B()
>>> b.b = 6
>>> b.b
6
>>> b.__dict__ = {}
>>> b.b
Traceback (most recent call last):
File "<pyshell#57>", line 1, in <module>
b.b
AttributeError: 'B' object has no attribute 'b'
However, I'm not sure whether this is guaranteed, or if it just happens to work. Especially in terms of supporting non-C Pythons, you may want to be careful.
Yes. It is possible to override(delete) the objects by assignment. Here is the example.
>>> class callable_objects:
def __init__(self, name, fame=None):
self.name = name
self.fame = fame
def _name(self):
if self.name[0] in ["a","b","c","d","e"]:
self._fame("1")
else:
self._fame("2")
def _fame(self, ifame):
if ifame == "1":
print "Ur fame is bad"
else:
print "Ur fame is very bad"
>>> c = callable_objects("ameet")
>>> callable_objects.__dict__
{'__module__': '__main__', '_fame': <function _fame at 0x02B5C370>, '__doc__': None, '__init__': <function __init__ at 0x02B5C330>, '_name': <function _name at 0x02B5C2F0>}
>>> c.__dict__
{'name': 'ameet', 'fame': None}
>>> callable_objects.__dict__ = c.__dict__
>>> callable_objects.__dict__
{'name': 'ameet', 'fame': None}