There is a code:
class C():
a=1
def f(self):
print "f func"
a=C()
print a.a
a.f()
>>> 1
>>> f func
And when i trying to get a.__dict__ or vars(a), it shows me just {}.
But
a.b=123
print a.__dict__
>>> {'b': 123}
I don't understand, why it is.
Looking at a.__dict__ or vars(a) gives you attributes of a, which is an instance. That instance initially has no attributes of its own. The attribute a that you created in your class definition is an attribute of the class itself, not of its instances. Later when you do a.b = 123, you create an attribute just on the instance, so you can see it in the instance __dict__. You will see the attribute a if you look at C.__dict__.
When you do print a.a, Python dynamically finds the attribute a on the class C. It sees that the instance doesn't have an attribute a, so it looks on the class and finds one there. That is the value that is printed. The class attribute is not "copied" to the instance when the instance is created; rather, every individual time you try to read the instance attribute, Python checks to see if it exists on the instance, and if not it looks it up on the class.
>>> C.a
1
>>> vars(C)['a']
1
(The whole vars dictionary for a class is rather long.)
Like your title says, it's a class variable. It belongs to the class, not the object. Python is doing some special logic behind the scenes to look on the type object for you when you call a.a. I'm not an expert, but I suspect it's finding a the same way it would find a method. In languages such as Java, I believe this sort of usage is discouraged. I don't know if it's discouraged in Python.
Related
Python noob here, trying to work more with classes and have broken my code down into a more simple example of what I am working with:
Lets say I have a class, with an instance and an attribute associated with that instance
class Foo(object):
def __init__(self, attribute=None):
self.attribute = attribute
def dosomething(self):
print('I did a thing!')
a = Foo()
a.attribute='bar'
Now, running the method from the instance 'a' works as expected
a.dosomething()
Out:
I did a thing!
However, trying to call the method from an attribute of 'a' results in error
a.attribute='bar'
a.attribute.dosomething()
AttributeError: 'str' object has no attribute 'dosomething'
This results in an attribute error, which is expected. 'a.attribute' is no longer a class type of 'Foo' but rather a class type of 'str'. My question is, can I do something inside the class to allow the attribute to use the class methods?
Furthermore, since I have not found any results for this during my interwebs searches, Im assuming that it likely is not recommended and probably not pythonic? (just a guess). I am open to suggestions on how to make this better, but ideally, I would like to keep the attribute the way it is while still being able to call the class methods. The dot syntax of attributes for classes really helps me keep things organized, but it is useless to me if it cannot call the methods in the class from which it originates.
Thanks in advance!
No, this doesn't work. And it really doesn't make sense if you understand how classes work.
That a.attribute is just a name for the string 'bar'. That string doesn't know anything about a, and shouldn't.1 There could be plenty of other names for the same string. For example:
>>> bar = 'bar'
>>> a.attribute = bar
>>> bar.dosomething()
AttributeError: 'str' object has no attribute 'dosomething'
That's exactly what you'd expect, right? But…
>>> a.attribute is bar
True
Since bar is the same object as a.attribute, it clearly has to do the same thing:
>>> a.attribute.dosomething()
AttributeError: 'str' object has no attribute 'dosomething'
1. There are some special cases where something like this would be useful, but they're solved by having the attribute not just be a string, but instead be some kind of smart object that works kind of like a string but also knows its class, instance, or parent. See the enum module in the stdlib for an example—and click on the source code link to see how it's implemented.
In this example the attribute is is a string when you execute a.attribute='bar' so if you were to do type(a.attribute) it would return string. So Python is looking for the attribute dosomething() in the str class and not finding it.
What you seem to be trying to do doesn't really make sense. At a guess, it seems like you've mixed up some concepts related to inheritance with your understanding of python's dot syntax for member reference, when these have nothing to do with each other.
You wrote
'a.attribute' is no longer a class type of 'Foo' but rather a class type of 'str'.
and this indicates a fundamental misunderstanding of what is going on. No state has changed – a is still the instance a, of type Foo. It has a member attribute, which is a string. The expression a.attribute is merely pointing to that string. If you need to call a method on a, you can still do so anywhere you were trying to call it on a.attribute:
>>> a.attribute = 'bar'
>>> a.doSomething()
I did a thing!
The common scenario in which an object of one type invokes a method that is not defined in its class is inheritance:
class Foo(object):
def superclass_method(self):
print "Hi"
class Bar(Foo):
pass
b = Bar()
b.superclass_method() # prints "Hi"
In this case, we say that b, an instance of Bar, is a Foo as well. Therefore any method that Foo defines, a Bar instance has access to.
If you tell us a bit more about what you're trying to accomplish, I can be more specific about whether and how you should be using inheritance. But the dot notation is just a way to talk about values attached to objects. It's literally just looking in the left object's dictionary for a value associated with the name on the right – foo.bar is equivalent to getattr(foo, 'bar').
Python provides us many possibilities on instance/class attribute, for example:
class A(object):
def __init__(self):
self.foo = "hello"
a = A()
There are many ways to access/change the value of self.foo:
direct access a.foo
inner dict a.__dict__['foo']
get and set a.__get__ and a.__set__,of course there two are pre-defined methods.
getattribute a.__getattribute__
__getattr__ and __setattr__
maybe more.
While reading source code, I always get lost of what's their ultimate access order? When I use a.foo, how do I know which method/attribute will get called actually?
I found out this great post that has a detailed explanation on object/class attribute lookup.
For object attribute lookup:
Assuming Class is the class and instance is an instance of Class, evaluating instance.foobar roughly equates to this:
Call the type slot for Class.__getattribute__ (tp_getattro). The default does this:
Does Class.__dict__ have a foobar item that is a data descriptor ?
If yes, return the result of Class.__dict__['foobar'].__get__(instance, Class).
Does instance.__dict__ have a 'foobar' item in it?
If yes, return instance.__dict__['foobar'].
Does Class.__dict__ have a foobar item that is not a data descriptor [9]?
If yes, return the result of Class.__dict__['foobar'].__get__(instance, klass). [6]
If the attribute still wasn't found, and there's a Class.__getattr__, call Class.__getattr__('foobar').
There is an illustrated image for this:
Please do check out the original blog if interested which gives a outstanding explanation on python class, attribute lookup, and metaclass.
bar = a.foo...
invokes a.__getattribute__('foo')
which in turn by default looks up a.__dict__['foo']
or invokes foo's .__get__() if defined on A.
The returned value would then be assigned to bar.
a.foo = bar...
invokes a.__getattribute__('foo')
which in turn by default looks up a.__dict__['foo']
or invokes foo's .__set__(bar) if defined on A.
Given an object it is easy to get the object type in python:
obj = SomeClass()
t = type(obj)
How can I do this without first creating an instance of the class?
Background: Once you have the type you easily can create instances of that type. Using this mechanism I want to pass a type to an object which will later create instances of that type. It would be very reasonable not to have to create an object first which will immediately be thrown away again.
See this example code:
class MyClass(object):
pass
if __name__ == '__main__':
o1 = MyClass()
c = MyClass
o2 = c()
print(type(o1), type(o2), MyClass)
Defining a class binds it to its name (here: MyClass), which is nothing else but a reference to that definition. In this example, issuing c = MyClass just mirrors the class reference to another variable, the contents of the variables c and MyClass now are exactly the same. Thus, you can instantiate objects of that class by calling either of them (i.e. MyClass() or c()), resulting in the same effect.
Furthermore, testing for the type of an instantiated object results in the exact same class reference. You can even go one step further and do:
o3 = type(o1)()
Which creates a new instance of the class of which o1 is.
This answer is for anyone who comes to this page wondering, "how can I check the type of a class without instantiating it in Python?"
If you are working with a variable that contains a class, rather than an object, you can check whether it is a certain class using the issubclass() built-in function.
Building off the previous answer:
>>> class MyClass(object):
... pass
...
>>> c = MyClass
>>> type(c)
<class 'type'>
>>> issubclass(c, MyClass)
True
Python provides us many possibilities on instance/class attribute, for example:
class A(object):
def __init__(self):
self.foo = "hello"
a = A()
There are many ways to access/change the value of self.foo:
direct access a.foo
inner dict a.__dict__['foo']
get and set a.__get__ and a.__set__,of course there two are pre-defined methods.
getattribute a.__getattribute__
__getattr__ and __setattr__
maybe more.
While reading source code, I always get lost of what's their ultimate access order? When I use a.foo, how do I know which method/attribute will get called actually?
I found out this great post that has a detailed explanation on object/class attribute lookup.
For object attribute lookup:
Assuming Class is the class and instance is an instance of Class, evaluating instance.foobar roughly equates to this:
Call the type slot for Class.__getattribute__ (tp_getattro). The default does this:
Does Class.__dict__ have a foobar item that is a data descriptor ?
If yes, return the result of Class.__dict__['foobar'].__get__(instance, Class).
Does instance.__dict__ have a 'foobar' item in it?
If yes, return instance.__dict__['foobar'].
Does Class.__dict__ have a foobar item that is not a data descriptor [9]?
If yes, return the result of Class.__dict__['foobar'].__get__(instance, klass). [6]
If the attribute still wasn't found, and there's a Class.__getattr__, call Class.__getattr__('foobar').
There is an illustrated image for this:
Please do check out the original blog if interested which gives a outstanding explanation on python class, attribute lookup, and metaclass.
bar = a.foo...
invokes a.__getattribute__('foo')
which in turn by default looks up a.__dict__['foo']
or invokes foo's .__get__() if defined on A.
The returned value would then be assigned to bar.
a.foo = bar...
invokes a.__getattribute__('foo')
which in turn by default looks up a.__dict__['foo']
or invokes foo's .__set__(bar) if defined on A.
I find the following example mildly surprising:
>>> class Foo:
def blah(self):
pass
>>> f = Foo()
>>> def bar(self):
pass
>>> Foo.bar = bar
>>> f.bar
<bound method Foo.bar of <__main__.Foo object at 0x02D18FB0>>
I expected the bound method to be associated with each particular instance, and to be placed in it at construction. It seems logical that the bound method would have to be different for each instance, so that it knows which instance to pass in to the underlying function - and, indeed:
>>> g = Foo()
>>> g.blah is f.blah
False
But my understanding of the process is clearly flawed, since I would not expect assigning a function into a class attribute would put it in instances that had already been created by then.
So, my question is two fold -
Why does assigning a function into a class apply retroactively to instances? What are the actual lookup rules and processes that make this so?
Is this something guaranteed by the language, or just something that happens to happen?
You want to blow your mind, try this:
f.blah is f.blah
That's right, the instance method wrapper is different each time you access it.
In fact an instance method is a descriptor. In other words, f.blah is actually:
Foo.blah.__get__(f, type(f))
Methods are not actually stored on the instance; they are stored on the class, and a method wrapper is generated on the fly to bind the method to the instance.
The instances do not "contain" the method. The lookup process happens dynamically at the time you access foo.bar. It checks to see if the instance has an attribute of that name. Since it doesn't, it looks on the class, whereupon it finds whatever attribute the class has at that time. Note that methods are not special in this regard. You'll see the same effect if you set Foo.bar = 2; after that, foo.bar will evalute to 2.
What is guaranteed by the language is that attribute lookup proceeds in this fashion: first the instance, then the class if the attribute is not found on the instance. (Lookup rules are different for special methods implicitly invoked via operator overloading, etc..)
Only if you directly assign an attribute to the instance will it mask the class attribute.
>>> foo = Foo()
>>> foo.bar
Traceback (most recent call last):
File "<pyshell#79>", line 1, in <module>
foo.bar
AttributeError: 'Foo' object has no attribute 'bar'
>>> foo.bar = 2
>>> Foo.bar = 88
>>> foo.bar
2
All of the above is a separate matter from bound/unbound methods. The class machinery in Python uses the descriptor protocol so that when you access foo.bar, a new bound method instance is created on the fly. That's why you're seeing different bound method instances on your different objects. But note that underlyingly these bound methods rely on the same code object, as defined by the method you wrote in the class:
>>> foo = Foo()
>>> foo2 = Foo()
>>> foo.blah.im_func.__code__ is foo2.blah.im_func.__code__
True