Python Class member variables initilialization? [duplicate] - python

This question already has answers here:
What is the difference between class and instance attributes?
(5 answers)
Closed 5 years ago.
Came across one Python Class and I am finding it hard to understand how and why its working . A simplified example of the class is :
class Test:
def __init__(self):
self.var = 1
otherVar = 2
def myPrinter(self):
print self.__dict__ # Prints {'var': 1}
print self.var
print self.otherVar # Doubt !!
print self.__dict__ # Prints {'var': 1}
ob = Test()
ob.myPrinter()
My doubt is with the self.otherVar call not throwing an error while self.__dict__ does not show reference to otherVar

It's because otherVar is an attribute of the class, while the var you setup in the __init__ is an attribute of the instance.
The otherVar is visible to the instance, because python first tries to get the instance attribute values, if the instance doesn't have it, then it checks its class attributes. If you define a var in both with different values, things may get confusing at first.
Well, do you know that comparison that a class is like a blueprint and the instance is the object built following it, right? So, var is an extra you added while creating the instance.
If you want to see otherVar, do Test.__dict__. It won't show you var, but all the class attributes.
Play a little with it and with time you are going to get used to it. Class attributes may be tricky, but extremely useful.

otherVar is a class member, not instance member, that's why it doesn't show in __dict__.
It appears in self.__class__.__dict__. (this way doesn't work in Python 2.x)
By the way, otherVar member value is shared across all instances and also accessible from type object: Test.otherVar
Example here: https://trinket.io/python3/d245351e58
For a more in depth explanation check here

Related

When is the parent class variables available to use in Python? [duplicate]

This question already has answers here:
Accessing attribute from parent class inside child class
(2 answers)
Closed 6 years ago.
class frozen(object) :
isFrozen = False
print 'In base'
class layer(frozen):
print isFrozen
I am trying to understand the inheritance concept in Python, the above lines are a silly example. "print" statement in the parent class is working as I try to create an object of layer class. But it's throwing an error at the "print" statement of the child class. Saying "isFrozen" is not defined.
But, if I comment out the "print" statement in child class, I can create an object of the child class and access "isFrozen" as "layerObject.isFrozen".
So, could anyone please point out my misunderstanding here?
Class body provides a namespace and classes (unlike functions) are parsed when the module is read (import time). Your problem is that you are calling isFrozen of the frozen class without the namespace. Also to take full advantage of inheritance you need an actual class instance which is usually referred to as self:
class Frozen(object):
isFrozen = False
def __init__(self):
print Frozen.isFrozen
print "From Base"
class Layer(Frozen):
def __init__(self):
print self.isFrozen ##this is defined by the parent
print "From subclass"
self.isFrozen = True
print self.isFrozen
In [7]: test_class = Layer()
False
From subclass
True
In [8]: test_class.isFrozen
Out[8]: True
And a RTFM is suggested here as well.

Why can't I add arbitrary members to object instances? [duplicate]

This question already has answers here:
Why can't you add attributes to object in python? [duplicate]
(2 answers)
Can't set attributes on instance of "object" class
(7 answers)
Closed 9 years ago.
I just realized that:
class A(object): pass
a = A()
a.x = 'whatever'
Works (does not raise an error and creates a new x member).
But this:
a = object()
a.x = 'whatever'
Raises:
AttributeError: 'object' object has no attribute 'x'
While I probably would never use this in real production code, I'm a bit curious about what the reason is for the different behaviors.
Any hints ?
Probably because of __slots__. By default your class have dict of all atributes which can be added to like in your first example. But that behaviour can bi overriden by using slots.
Also, some classes like datetime which are implemented in C also can not be extended with new attributes at runtime.
Workaround for such classes is to do something like :
class MyObject(): # extend that class, here we extend object
pass # add nothing to the class
o = MyObject()
o.x = 'whatever' # works

Loop over instances of a class to find attribute that equals a keyword [duplicate]

This question already has answers here:
Printing all instances of a class
(8 answers)
Closed 9 years ago.
Okay, so what I am trying to do is to create a function that will find an object instance based on the value of a specific attribute that all objects of the class share. Essentially, I want Python to search through the specific attribute of each instance of the class, and check it against another value, and if it finds a match to do some stuff. In pseudocode:
for each instance of Class:
if search_keyword is in instance.attribute:
do some stuff
found = True
if found is True:
tell_user("Found instance!")
If more detail is required on the nature of my inquiry, then:
What I am doing is essentially using the object as an extended dictionary. I have multiple attributes attached to the object, and I want to search through them. I am essentially using it as a storage container, which I need to search through.
If there is a better way to store said information other than objects, please share.
I'm essentially using it as a dictionary with multiple keys.
You could do this easily enough by having a class attribute which is a list of all instances of that class ever created, and having the __init__ of each instance of the class add the instance to the list.
class Foo(object):
list_of_all_foos = []
def __init__(self):
Foo.list_of_all_foos.append(self)
Then to search all the Foo instances you've created:
for foo_instance in Foo.list_of_all_foos:
if search_keyword is in foo_instance.attribute:
do some stuff
found = True
if found is True:
tell_user("Found instance!")
Alternatively, to do this with a class method, which might be a little more idiomatic:
class Foo(object):
list_of_all_foos = []
#classmethod
def create_foo_and_add_to_list(cls, *args, **kwargs):
new_foo = cls(*args, **kwargs)
Foo.list_of_all_foos.append(new_foo)
return new_foo

Terrifying initial values - mutable types share same reference? [duplicate]

This question already has answers here:
How to avoid having class data shared among instances?
(7 answers)
Closed 9 years ago.
I just got owned. I couldn't believe that this was true, but upon testing it, I found it to be:
class A(object):
v = []
a = A()
b = A()
What do you think that the following code will return?
a.v is b.v
What about this code?
a.v.append(1)
a.v[0] == b.v[0]
Sure enough, a.v is b.v, they both share the same reference to the same list. Coming from a, well, every other programming language background, how does this make sense?
In Java, if I were to write a class like this:
class A {
public Object[] v = new Object[]{};
}
...I would never, in my wildest dreams, think that two instances of the class would share the same reference to the array.
My main question is this, is there something equivalent for initial values in Python classes as in Java, C#, etc.? Why do all instances of the class share the same reference to the same list?
You have defined a class attribute instead of an instance attribute. Python is doing the right thing.
Instead of
class A(object):
v = [] # Class attribute, shared across all instances!
you need
class A(object):
def __init__(self): # Instance attribute, created anew for each new object
self.v = []
Java syntax is different to Python's. It's not a good idea to just try to guess the right thing to use based on your Java knowledge
class A(object):
v = [] # class attribute
class A(object):
def __init__(self):
self.v = [] # instance attribute
Ok, the rules are kinda funny.
If you try to access self.v, first Python looks for an instance attribute, if there isn't one it looks at the class, and then the parent classes until it finds one or raises an attribute error.
When you assign to self.v it always binds it to an instance attribute even if it wasn't before.
Then there are descriptors...
That's because v is a class attribute (think static member variable in C++).
If you want a non-shared member attribute, you have to declare it in the constructor:
class A(object):
def __init__(self):
selv.v = []
class A(object):
v = []
here v is a class attribute not instance attribute, They are only defined once, during the class definition. So, that's why the're are pointing to the same object.
Use instance attribute instead:
class A(object):
def __init__(self):
self.v = [] #different for each instance
a= A()
b = A()
print a is b #prints False

python class attributes: unexpected behaviour [duplicate]

This question already has answers here:
How to avoid having class data shared among instances?
(7 answers)
Closed 9 years ago.
i just have a puzzling question abou class attributes in python.
consider the following class below:
class A:
__lst = []
def add(self, str):
self.__lst.append(str)
print len(self.__lst)
i tried to make two instances x and y and i got this:
>>> x = A()
>>> x.add('aaa')
1
>>> x.add('bbb')
2
>>> y = A()
>>> y.add('aaa')
3
>>> y.add('bbb')
4
i was expecting that the instance of y will have a separate copy of the list attribute but it seems that the list just gets bigger even if you use another object to add elements to the list. it's simply weird.
can anybody please enlighten me on this matter?
thanks a lot in advance for your help. :-)
If you define an attribute inside of the class body then it will be a class attribute, and it will be shared by all instances. In your code self.__lst is going to be a reference to A.__lst.
To have a separate list for each attribute, define it as self.__lst inside of the __init__() function:
class A(object):
def __init__(self):
self.__lst = []
def add(self, s):
self.__lst.append(s)
print len(self.__lst)
In addition to the change referenced above, I also made some minor modifications so that your code follows some Python best practices: inheriting from object (new-style class) and not using str (or any other built-in name) as a variable name.
Variables declared inside a class but not by means of self are class-level properties (like your __lst). They are equivalent to Java's static. If you want your property to be unique for all instances, you need to declare them via self (i.e., self.__lst).

Categories

Resources