I am relatively new to Python and was hoping someone could explain the following to me:
class MyClass:
Property1 = 1
Property2 = 2
print MyClass.Property1 # 1
mc = MyClass()
print mc.Property1 # 1
Why can I access Property1 both statically and through a MyClass instance?
The code
class MyClass:
Property1 = 1
creates a class MyClass which has a dict:
>>> MyClass.__dict__
{'Property1': 1, '__doc__': None, '__module__': '__main__'}
Notice the key-value pair 'Property1': 1.
When you say MyClass.Property1, Python looks in the dict MyClass.__dict__ for the key Property1 and if it finds it, returns the associated value 1.
>>> MyClass.Property1
1
When you create an instance of the class,
>>> mc = MyClass()
a dict for the instance is also created:
>>> mc.__dict__
{}
Notice this dict is empty. When you say mc.Property1, Python first looks in mc.__dict__ for the 'Property1' key. Since it does not find it there, it looks in the dict of mc's class, that is, MyClass.__dict__.
>>> mc.Property1
1
Note that there is much more to the story of Python attribute access. (I haven't mentioned the important rules concerning descriptors, for instance.) But the above tells you the rule for most common cases of attribute access.
Related
I used setattr method to set column names from an Excel file as attribute of object. However, these names include spaces like "Vendor name". How can I access the attribute like this?
for k in self.df.columns.values.tolist():
setattr(self,k,self.df[k])
With getattr, of course:
>>> class MyClass: pass
...
>>> my_object = MyClass()
>>> setattr(my_object, 'spaces are considered harmful', 42)
>>> getattr(my_object, 'spaces are considered harmful')
42
Or, you can always access the namespace of a custom class (where you haven't defined __slots__) by using the namespace directly:
>>> vars(my_object) is my_object.__dict__
True
>>> vars(my_object)
{'spaces are considered harmful': 42}
>>> my_object.__dict__
{'spaces are considered harmful': 42}
>>> vars(my_object)['spaces are considered harmful']
42
>>> my_object.__dict__['spaces are considered harmful']
42
Although really, instead of a custom class, it sounds like you want some container that is a sort of mapping from strings to other objects.
I found that some classes contain a __init__ function, and some don’t. I’m confused about something described below.
What is the difference between these two pieces of code:
class Test1(object):
i = 1
and
class Test2(object):
def __init__(self):
self.i = 1
I know that the result or any instance created by these two class and the way of getting their instance variable are pretty much the same. But is there any kind of “default” or “hidden” initialization mechanism of Python behind the scene when we don’t define the __init__ function for a class? And why I can’t write the first code in this way:
class Test1(object):
self.i = 1
That’s my questions. Thank you very much!
Thank you very much Antti Haapala! Your answer gives me further understanding of my questions. Now, I understand that they are different in a way that one is a "class variable", and the other is a "instance variable". But, as I tried it further, I got yet another confusing problem.
Here is what it is. I created 2 new classes for understanding what you said:
class Test3(object):
class_variable = [1]
def __init__(self):
self.instance_variable = [2]
class Test4(object):
class_variable = 1
def __init__(self):
self.instance_variable = 2
As you said in the answer to my first questions, I understand the class_variable is a "class variable" general to the class, and should be passed or changed by reference to the same location in the memory. And the instance_variable would be created distinctly for different instances.
But as I tried out, what you said is true for the Test3's instances, they all share the same memory. If I change it in one instance, its value changes wherever I call it.
But that's not true for instances of Test4. Shouldn't the int in the Test4 class also be changed by reference?
i1 = Test3()
i2 = Test3()
>>> i1.i.append(2)
>>> i2.i
[1, 2]
j1 = Test4()
j2 = Test4()
>>> j1.i = 3
>>> j2.i
1
Why is that? Does that "=" create an "instance variable" named "i" without changing the original "Test4.i" by default? Yet the "append" method just handles the "class variable"?
Again, thank you for your exhaustive explanation of the most boring basic concepts to a newbie of Python. I really appreciate that!
In python the instance attributes (such as self.i) are stored in the instance dictionary (i.__dict__). All the variable declarations in the class body are stored as attributes of the class.
Thus
class Test(object):
i = 1
is equivalent to
class Test(object):
pass
Test.i = 1
If no __init__ method is defined, the newly created instance usually starts with an empty instance dictionary, meaning that none of the properties are defined.
Now, when Python does the get attribute (as in print(instance.i) operation, it first looks for the attribute named i that is set on the instance). If that fails, the i attribute is looked up on type(i) instead (that is, the class attribute i).
So you can do things like:
class Test:
i = 1
t = Test()
print(t.i) # prints 1
t.i += 1
print(t.i) # prints 2
but what this actually does is:
>>> class Test(object):
... i = 1
...
>>> t = Test()
>>> t.__dict__
{}
>>> t.i += 1
>>> t.__dict__
{'i': 2}
There is no i attribute on the newly created t at all! Thus in t.i += 1 the .i was looked up in the Test class for reading, but the new value was set into the t.
If you use __init__:
>>> class Test2(object):
... def __init__(self):
... self.i = 1
...
>>> t2 = Test2()
>>> t2.__dict__
{'i': 1}
The newly created instance t2 will already have the attribute set.
Now in the case of immutable value such as int there is not that much difference. But suppose that you used a list:
class ClassHavingAList():
the_list = []
vs
class InstanceHavingAList()
def __init__(self):
self.the_list = []
Now, if you create 2 instances of both:
>>> c1 = ClassHavingAList()
>>> c2 = ClassHavingAList()
>>> i1 = InstanceHavingAList()
>>> i2 = InstanceHavingAList()
>>> c1.the_list is c2.the_list
True
>>> i1.the_list is i2.the_list
False
>>> c1.the_list.append(42)
>>> c2.the_list
[42]
c1.the_list and c2.the_list refer to the exactly same list object in memory, whereas i1.the_list and i2.the_list are distinct. Modifying the c1.the_list looks as if the c2.the_list also changes.
This is because the attribute itself is not set, it is just read. The c1.the_list.append(42) is identical in behaviour to
getattr(c1, 'the_list').append(42)
That is, it only tries read the value of attribute the_list on c1, and if not found there, then look it up in the superclass. The append does not change the attribute, it just changes the value that the attribute points to.
Now if you were to write an example that superficially looks the same:
c1.the_list += [ 42 ]
It would work identical to
original = getattr(c1, 'the_list')
new_value = original + [ 42 ]
setattr(c1, 'the_list', new_value)
And do a completely different thing: first of all the original + [ 42 ] would create a new list object. Then the attribute the_list would be created in c1, and set to point to this new list. That is, in case of instance.attribute, if the attribute is "read from", it can be looked up in the class (or superclass) if not set in the instance, but if it is written to, as in instance.attribute = something, it will always be set on the instance.
As for this:
class Test1(object):
self.i = 1
Such thing does not work in Python, because there is no self defined when the class body (that is all lines of code within the class) is executed - actually, the class is created only after all the code in the class body has been executed. The class body is just like any other piece of code, only the defs and variable assignments will create methods and attributes on the class instead of setting global variables.
I understood my newly added question. Thanks to Antti Haapala.
Now, when Python does the get attribute (as in print(instance.i) operation, it first looks for the attribute named i that is set on the instance). If that fails, the i attribute is looked up on type(i) instead (that is, the class attribute i).
I'm clear about why is:
j1 = Test4()
j2 = Test4()
>>> j1.i = 3
>>> j2.i
1
after few tests. The code
j1.3 = 3
actually creates a new instance variable for j1 without changing the class variable. That's the difference between "=" and methods like "append".
I'm a newbie of Python coming from c++. So, at the first glance, that's weird to me, since I never thought of creating a new instance variable which is not created in the class just using the "=". It's really a big difference between c++ and Python.
Now I got it, thank you all.
I'm a newbie in Python. After reading some chapters of Python Tutorial Release 2.7.5, I'm confused about Python scopes and namespaces. This question may be duplicated because I don't know what to search for.
I created a class and an instance. Then I deleted the class using del. But the instance still works properly. Why?
>>>class MyClass: # define a class
... def greet(self):
... print 'hello'
...
>>>instan = MyClass() # create an instantiation
>>>instan
<__main__.MyClass instance at 0x00BBCDC8>
>>>instan.greet()
hello
>>>dir()
['instan', 'MyClass', '__builtins__', '__doc__', '__name__', '__package__']
>>>
>>>
>>>del MyClass
>>>dir()
['instan', '__builtins__', '__doc__', '__name__', '__package__']
>>>instan
<__main__.MyClass instance at 0x00BBCDC8> # Myclass doesn't exist!
>>>instan.greet()
hello
I know little about OOP so this question may seem simple. Thanks in advance.
Python is a garbage collected language. When you do del MyClass, you do not actually delete the 'class object' (classes are objects too), but you only remove the 'name' MyClass from the current namespace, which is some sort of reference to the class object. Any object stays alive as long as it is referenced by something. Since instances reference their own class, the class will stay alive as long as there is at least one instance alive.
One thing to be careful about is when you redefine a class (e.g. on the command line):
In [1]: class C(object):
...: def hello(self):
...: print 'I am an instance of the old class'
In [2]: c = C()
In [3]: c.hello()
I am an instance of the old class
In [4]: class C(object): # define new class and point C to it
...: def hello(self):
...: print 'I am an instance of the new class'
In [5]: c.hello() # the old object does not magically become a new one
I am an instance of the old class
In [6]: c = C() # point c to new object, old class and object are now garbage
In [7]: c.hello()
I am an instance of the new class
Any existing instances of the old class will continue to have the old behavior, which sort of makes sense considering the things I mentioned. The relation between name-spaces and objects is a bit particular to python, but is not that hard once you get it. A good explanation is given here.
When you delete a variable using del, you delete the variable name and your own reference to the object in the variable, not the object itself.
The object you created still contains its own reference to the class. In general, as long as someone still holds a reference to any object (including a class definition) it won't be deleted by the garbage collector.
Python doesn't store values in variables, it assigns names to objects. The locals() function will return all the names in the current namespace (or more specifically, the current scope). Let's start up a new interpreter session and see what locals() will give us.
>>> locals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, '__package__': None}
The only names currently in the namespace are built in names that Python puts there at start up. Here a quick one-liner to show us only the names we've assigned:
>>> {k:v for k,v, in locals().iteritems() if k[0] != '_'}
{}
That's better. Don't worry about how that one-liner works, let's move on and create a class.
>>> class C(object):
greeting = "I'm the first class"
When we define a class, it's name in places in the current scope:
>>> {k:v for k,v, in locals().iteritems() if k[0] != '_'}
{'C': <class '__main__.C'>}
The part is Python's way of saying that there's an object that's too big to print out, but it's the class object we defined. Let's look at the memory address that our class object is stored at. We can use the id() function to find out.
>>> id(C)
18968856
The number that id() returns is the memory location of the argument. If you run these commands yourself, you'll see a different number, but the number doesn't change during a single session.
>>> id(C)
18968856
Now let's create an instance.
>>> c = C()
>>> c.greeting
"I'm the first class"
Now when we look at locals(), we can see both our class object, and our instance object.
>>> {k:v for k,v, in locals().iteritems() if k[0] != '_'}
{'C': <class '__main__.C'>, 'c': <__main__.C object at 0x011BDED0>}
Every instance object has a special member __class__ that is a reference to the class object that the instance is an instance of.
>>> c.__class__
<class '__main__.C'>
If we call id() on that variable, we can see it's a reference to the class C we just defined:
>>> id(c.__class__)
18968856
>>> id(c.__class__) == id(C)
True
Now let's delete the name C from out local namespace:
>>> del C
>>> {k:v for k,v, in locals().iteritems() if k[0] != '_'}
{'c': <__main__.C object at 0x011BDED0>}
>>> C
Traceback (most recent call last):
File "<pyshell#16>", line 1, in <module>
C
NameError: name 'C' is not defined
That's exactly what we expect. The name C is no longer assigned to anything. However, our instance still has a reference to the class object.
>>> c.__class__
<class '__main__.C'>
>>> id(c.__class__)
18968856
As you can see, the class still exists, you just can't refer to it through the name C in the local namespace.
Let's create a second class with the name C.
>>> class C(object):
greeting = "I'm the second class"
>>> {k:v for k,v, in locals().iteritems() if k[0] != '_'}
{'C': <class '__main__.C'>, 'c': <__main__.C object at 0x011BDED0>}
If we create an instance of the second class, it behaves like you noticed:
>>> c2 = C()
>>> c2.greeting
"I'm the second class"
>>> c.greeting
"I'm the first class"
To see why, let's look at the id of this new class. We can see that the new class object is stored in a different location from our first one.
>>> id(C)
19011568
>>> id(C) == id(C.__class__)
False
This is why the instances can still work properly: both class object still exists separately, and each instance holds a reference to its object.
I was reading the python descriptors and there was one line there
Python first looks for the member in the instance dictionary. If it's
not found, it looks for it in the class dictionary.
I am really confused what is instance dict and what is class dictionary
Can anyone please explain me with code what is that
I was thinking of them as same
An instance dict holds a reference to all objects and values assigned to the instance, and the class level dict holds all references at the class namespace.
Take the following example:
>>> class A(object):
... def foo(self, bar):
... self.zoo = bar
...
>>> i = A()
>>> i.__dict__ # instance dict is empty
{}
>>> i.foo('hello') # assign a value to an instance
>>> i.__dict__
{'zoo': 'hello'} # this is the instance level dict
>>> i.z = {'another':'dict'}
>>> i.__dict__
{'z': {'another': 'dict'}, 'zoo': 'hello'} # all at instance level
>>> A.__dict__.keys() # at the CLASS level, only holds items in the class's namespace
['__dict__', '__module__', 'foo', '__weakref__', '__doc__']
I think, you can understand with this example.
class Demo(object):
class_dict = {} # Class dict, common for all instances
def __init__(self, d):
self.instance_dict = d # Instance dict, different for each instance
And it's always possible to add instance attribute on the fly like this: -
demo = Demo({1: "demo"})
demo.new_dict = {} # A new instance dictionary defined just for this instance
demo2 = Demo({2: "demo2"}) # This instance only has one instance dictionary defined in `init` method
So, in the above example, demo instance has now 2 instance dictionary - one added outside the class, and one that is added to each instance in __init__ method. Whereas, demo2 instance has just 1 instance dictionary, the one added in __init__ method.
Apart from that, both the instances have a common dictionary - the class dictionary.
Those dicts are the internal way of representing the object or class-wide namespaces.
Suppose we have a class:
class C(object):
def f(self):
print "Hello!"
c = C()
At this point, f is a method defined in the class dict (f in C.__dict__, and C.f is an unbound method in terms of Python 2.7).
c.f() will make the following steps:
look for f in c.__dict__ and fail
look for f in C.__dict__ and succeed
call C.f(c)
Now, let's do a trick:
def f_french():
print "Bonjour!"
c.f = f_french
We've just modified the object's own dict. That means, c.f() will now print Bounjour!. This does not affect the original class behaviour, so that other C's instances will still speak English.
Class dict is shared among all the instances (objects) of the class, while each instance (object) has its own separate copy of instance dict.
You can define attributes separately on a per instance basis rather than for the whole class
For eg.
class A(object):
an_attr = 0
a1 = A()
a2 = A()
a1.another_attr = 1
Now a2 will not have another_attr. That is part of the instance dict rather than the class dict.
Rohit Jain has the simplest python code to explain this quickly. However, understanding the same ideas in Java can be useful, and there is much more information about class and instance variables here
Could you clarify some ideas behind Python classes and class instances?
Consider this:
class A():
name = 'A'
a = A()
a.name = 'B' # point 1 (instance of class A is used here)
print a.name
print A.name
prints:
B
A
if instead in point 1 I use class name, output is different:
A.name = 'B' # point 1 (updated, class A itself is used here)
prints:
B
B
Even if classes in Python were some kind of prototype for class instances, I'd expect already created instances to remain intact, i.e. output like this:
A
B
Can you explain what is actually going on?
First of all, the right way in Python to create fields of an instance (rather than class fields) is using the __init__ method. I trust that you know that already.
Python does not limit you in assigning values to non-declared fields of an object. For example, consider the following code:
class Empty: pass
e = Empty()
e.f = 5
print e.f # shows 5
So what's going in your code is:
You create the class A with a static field name assigned with A.
You create an instance of A, a.
You create a new field for the object a (but not for other instances of A) and assign B to it
You print the value of a.name, which is unique to the object a.
You print the value of the static field A.name, which belongs to the class
Perhaps this example may make things more help clarify. Recall that Python names are not storage (as variables are in other languages) but references to storage. You can find what a name refers to with id(name). The identity operator x is y tells whether two names point at the same object.
>>> class A(object):
... name = 'A'
...
>>> x = A()
>>> A.name is x.name
True
>>> x.name = 'fred' # x.name was bound to a new object (A.name wasn't)
>>> A.name is x.name
False
>>> x = A() # start over
>>> A.name is x.name
True # so far so good
>>> A.name = 'fred'
>>> A.name is x.name
True # this is somewhat counter-intuitive
You also should look at these SO threads for further explanations:
Static class variables in Python
In Python how can I access "static" class variables within class methods
And an official tutorial:
http://docs.python.org/tutorial/classes.html#SECTION0011320000000000000000
Keep in mind that the assignment "=" operator in python behaves differently than C++ or Java:
http://docs.python.org/reference/simple_stmts.html#assignment-statements