Classes as well as their instances in python uses dictionary like data structure to store the information.
So for each class definition, a dictionary will be allocated where the class level information (class variables) will be stored. And for each instance of that particular class, a separate dictionary(self) will be allocated where the instance specific information(instance variables) will be stored.
So now the next question is: How the lookup for a particular name will be performed ??
And answer to this question is that if you are accessing the names through some instance, the instance specific dictionary will be searched first and if the name is not found there, then the class dictionary will be searched for that name. So if the same value is defined at both levels that former one will be overridden.
Note that when you write d['key'] = val where d is a dictionary, 'key' will automatically be added to the dictionary if not already present. Otherwise the current value will be overwritten. Keep this in mind before reading the further explanation.
Now lets go through the code you have used to describe your problem:
MyClass1
class MyClass1:
q=1
def __init__(self,p):
self.p=p
def AddSomething(self,x):
self.q = self.q+x
1. my = Myclass1(2) #create new instance and add variables to it.
MyClass = {"q" : 1}
my = {"p" : 2}
2. my.p # =2, p will be taken from Dictionary of my-instance.
3. my.q # =1, q will be takn from MyClass dict. (Not present in dictionary of my-instance).
4. my.AddSomething(7) # This method access the value of q (using self.q) first
# which is not defined in my dict and hence will be taken
# from dictionary of MyClass. After the addition operation,
# the sum is being stored in self.q. Note that now we are
# adding the name q to Dictionary of my-instance and hence
# a new memory space will be created in Dictionary of my-instance
# and the future references to self.q will fetch the value
# of self.q from dictionary of my-instance.
MyClass = {"q" : 1}
my = {"p" : 2, "q" : 8}
5. my.q # =8, q now is available in dictionary of my-instance.
Answer from Shasha99 on Stack Overflowpython - Class attributes and their initialization - Stack Overflow
python - Getting attributes of a class - Stack Overflow
Nested attributes (or classes)
Hmm... I'm not able to reproduce your error. Here is what I put in, assuming that there are tabs in the appropriate places.
class A(object):
class B(object):
def __init__(self,C):
self.C = C
b = A.B(10)This runs without error.
However, based on your description, I don't think that this is quite what you want. The key difference to look for is between classes, and instances of the class. Let's look at the code closely. First, it defines a class, 'A'. Next, it defines a class 'B', as an attribute of the class. It is then valid to instantiate something of type B in either of the following ways.
a = A(); b = a.B() b = A.B()
However, neither of these will let you do a.b.C, because the object a only knows about the class B, not the instances of that class. In general, therefore, you would have class A make an instance of class B in its constructor. This would look like the following.
class A(object):
def __init__(self,C):
self.b = B(C)
class B(object):
def __init__(self,C):
self.C = C
a = A(10)
print a.b.C
This way, instead of A holding the class definition of B, it is holding a single instance, b.
Please help me understand what methods and classes are.
What happens if both instance attribute and class attribute are defined?
In that case, the instance namespace takes precedence over the class namespace. If there is an attribute with the same name in both, the instance namespace will be checked first and its value returned.
What is a Python namespace?
A Python namespace is a mapping from names to objects, with the property that there is zero relation between names in different namespaces. Namespaces are usually implemented as Python dictionaries, although this is abstracted away.
Python class method versus instance method: Whatโs the difference?
In Python, a class method is a method that is invoked with the class as the context. This is often called a static method in other programming languages. An instance method, on the other hand, is invoked with an instance as the context.
Videos
Classes as well as their instances in python uses dictionary like data structure to store the information.
So for each class definition, a dictionary will be allocated where the class level information (class variables) will be stored. And for each instance of that particular class, a separate dictionary(self) will be allocated where the instance specific information(instance variables) will be stored.
So now the next question is: How the lookup for a particular name will be performed ??
And answer to this question is that if you are accessing the names through some instance, the instance specific dictionary will be searched first and if the name is not found there, then the class dictionary will be searched for that name. So if the same value is defined at both levels that former one will be overridden.
Note that when you write d['key'] = val where d is a dictionary, 'key' will automatically be added to the dictionary if not already present. Otherwise the current value will be overwritten. Keep this in mind before reading the further explanation.
Now lets go through the code you have used to describe your problem:
MyClass1
class MyClass1:
q=1
def __init__(self,p):
self.p=p
def AddSomething(self,x):
self.q = self.q+x
1. my = Myclass1(2) #create new instance and add variables to it.
MyClass = {"q" : 1}
my = {"p" : 2}
2. my.p # =2, p will be taken from Dictionary of my-instance.
3. my.q # =1, q will be takn from MyClass dict. (Not present in dictionary of my-instance).
4. my.AddSomething(7) # This method access the value of q (using self.q) first
# which is not defined in my dict and hence will be taken
# from dictionary of MyClass. After the addition operation,
# the sum is being stored in self.q. Note that now we are
# adding the name q to Dictionary of my-instance and hence
# a new memory space will be created in Dictionary of my-instance
# and the future references to self.q will fetch the value
# of self.q from dictionary of my-instance.
MyClass = {"q" : 1}
my = {"p" : 2, "q" : 8}
5. my.q # =8, q now is available in dictionary of my-instance.
q=1 inside the class is a class attribute, associated with the class as a whole and not any particular instance of the class. It is most clearly accessed using the class itself: MyClass1.q.
A instance attribute is assigned directly to an instance of a class, usually in __init__ by assigning to self (such as with self.p = p), but you can assign attributes to an instance at any time.
Class attributes can be read either using the class binding (MyClass.q) or an instance binding (my.q, assuming it is not shadowed by an instance attribute with the same name). They can only be set, however, using a class binding. Setting a value with an instance binding always modifies an instance attribute, creating it if necessary. Consider this example:
>>> a = MyClass1()
>>> a.q
1
>>> a.q = 3 # Create an instance attribute that shadows the class attribute
3
>>> MyClass1.q
1
>>> b = MyClass1()
>>> b.q # b doesn't have an instance attribute q, so access the class's
1
Try the inspect module. getmembers and the various tests should be helpful.
EDIT:
For example,
class MyClass(object):
a = '12'
b = '34'
def myfunc(self):
return self.a
>>> import inspect
>>> inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a)))
[('__class__', type),
('__dict__',
<dictproxy {'__dict__': <attribute '__dict__' of 'MyClass' objects>,
'__doc__': None,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'MyClass' objects>,
'a': '34',
'b': '12',
'myfunc': <function __main__.myfunc>}>),
('__doc__', None),
('__module__', '__main__'),
('__weakref__', <attribute '__weakref__' of 'MyClass' objects>),
('a', '34'),
('b', '12')]
Now, the special methods and attributes get on my nerves- those can be dealt with in a number of ways, the easiest of which is just to filter based on name.
>>> attributes = inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a)))
>>> [a for a in attributes if not(a[0].startswith('__') and a[0].endswith('__'))]
[('a', '34'), ('b', '12')]
...and the more complicated of which can include special attribute name checks or even metaclasses ;)
def props(cls):
return [i for i in cls.__dict__.keys() if i[:1] != '_']
properties = props(MyClass)