Adding variables to a class - python

Given a class Mitarbeiter with the constructor __init__ which is creating 3 variables. Can additional variables be added by another method in python? Example below:
class Mitarbeiter:
species = "Homo sapiens"
#Klassenmethoden ändern nur Klassenattribute
#statische Methoden verwenden werder Instanz- noch Klassenattribute
#konstruktor
def __init__ (self, vorname, name, personalnummer):
self.__vorname = vorname
self.__name = name
self.__personalnummer = personalnummer
def _def_abteilung(self, abteilung):
self.__abteilung = abteilung
def _set_vorgesetzter (self, vorgesetzter):
self.__vorgesetzer = vorgesetzter
#property
def get_abteilung(self,):
return self.__abteilung
when I create an Object of Mitarbeiter with the variables vorname, name and personalnummer I can call later the method _def_abteilung to set some more information to the Object Mitarbeiter.
ma1 = Mitarbeiter("Franz", "Bauer", 736) #--> Works
ma1._def_abteilung("Test") #--> Works
ma1.abteilung #--> does not work, any Ideas?

The "_name is private" convention is a convention (privacy isn't enforced in any way),
"__name" mangles the name so ma1.__abteilung literally doesn't exist outside the class.
See What is the meaning of single and double underscore before an object name? and Python Name Mangling and How to Use Underscores
You can set attributes for an object anywhere -- if you changed self.__abteilung to self.abteilung, that name wouldn't be mangled by the interpreter and you would see the abteilung attribute defined on all Mitarbeiter objects.
Consider the following TestClass example:
class TestClass:
def __init__(self, a):
self.a = a
def set_b(self, b):
self.b = b
def set_mangled(self, m):
self.__m = m
print("Mangled", self.__m)
def get_mangled(self):
return self.__m
The a attribute is set in the __init__, so t.a always exists
t = TestClass(0)
print(t.a) # 0
print(t.b) # AttributeError
The b attribute is only set in the set_b method, so it only exists on an object after that method is called. The method can set an attribute of the object using the reference self. Trying to print t.b before setting it throws an AttributeError
t.set_b(10)
print(t.a) # 0
print(t.b) # 10
print(t.c) # AttributeError
The c attribute is set only once you run the line t.c = 100. As you can see, it is possible to set the attribute from outside the class. Trying to access t.c before setting it throws an AttributeError.
t.c = 100
print(t.a) # 0
print(t.b) # 10
print(t.c) # 100
The __m attribute is defined as a mangled name. Inside the class, it is accessed using self.__m. Outside the class, the name is mangled to _TestClass__m, so it is not accessible as t.__m or t.m.
t.set_mangled(1000) # Mangled: 1000
print(t.get_mangled()) # 1000
print(t._TestClass__m) # 1000
print(t.__m) # AttributeError: 'TestClass' object has no attribute '__m'
print(t.m) # AttributeError: 'TestClass' object has no attribute 'm'

Related

Python, how come we can create class variables that were not defined in class creation?

Let's say we have this simple Python code
class MyClass(object):
class_var = 1
def __init__(self, i_var):
self.i_var = i_var
Correct me if I get any of this wrong:
Class_Var is a class variable that is the same for all instances of MyClass object.
I_Var is an instance variable that only exists in instances of the MyClass object
foo = MyClass(2)
bar = MyClass(3)
foo.class_var, foo.i_var
## 1, 2
bar.class_var, bar.i_var
## 1, 3
Class variables are also properties of the class itself.
MyClass.class_var ##
## 1
MyClass.I_var should error out, correct?
Does that mean that class variables can be considered like instance variables of the class object itself (since all classes are objects) ?
MyClass.new_attribute = 'foo'
print(hasattr(ObjectCreator, 'new_attribute'))
That should return true. And
print (MyClass.new_attribute)
should return foo.
How come we can create a new class variable that was not defined in the original definition for that class?
Is
MyClass.new_attribute = 'foo'
the exact same thing as creating that class attribute in the original definition?
class MyClass(object):
class_var = 1
new_attribute = 'foo'
So we can create new class attributes at runtime? How does that not interfere with the init constructor that creates the class object and has those class variables as instance variables of the class object?
A class object is just an instance of yet another type, usually type (though you can change this using the metaclass parameter to the class statement).
Like most other instances, you can add arbitrary instance attributes to a class object at any time.
Class attributes and instance attributes are wholly separate; the former are stored on the class object, the latter on instances of the class.
There's nothing particularly special about __init__; it's just another method that, among other things, can attached new attributes to an object. What is special is that __init__ is called automatically when you create a new instance of the class by calling the class. foo = MyClass(2) is equivalent to
foo = MyClass.__new__(MyClass, 2)
foo.__init__(2)
The class statement
class MyClass(object):
class_var = 1
def __init__(self, i_var):
self.i_var = i_var
is roughly equivalent to
def my_class_init(self, i_var):
self.i_var = i_var
MyClass = type('MyClass', (object,), {'class_var': 1, '__init__: my_class_init})
The 3-argument form of type lets you pass a dict that creates class attributes when you first create the class, but you can always assign attributes after the fact as well:
MyClass = type('MyClass', (object,), {})
MyClass.class_var = 1
MyClass.__init__ = my_class_init
Just to blow your mind a little bit more, the call to type can be though of as
MyClass = type.__new__(type, 'MyClass', (object,), {...})
MyClass.__init__('MyClass', (object,), {...})
though unless you define a custom metaclass (by subclassing type), you never have to think about type itself having __new__ and __init__ methods.
Does that mean that class variables can be considered like instance variables of the class object itself (since all classes are objects) ?
Yes.
How come we can create a new class variable that was not defined in the original definition for that class?
Because Python is a dynamic language. A class can be created at run time - in fact, it is created at run time when you run Python interactively.
So we can create new class attributes at runtime?
Yes, unless the metaclass (the class of the class) has forbidden it.
How does that not interfere with the init constructor that creates the class object and has those class variables as instance variables of the class object?
The only rule is that you cannot use something that has not yet be defined or something that has been deleted:
>>> class MyClass(object):
class_var = 1
def __init__(self, i_var):
self.i_var = i_var
self.j_var = self.class_var + 1
>>> a = MyClass(2)
>>> del MyClass.class_var
>>> b = MyClass(3)
Traceback (most recent call last):
File "<pyshell#39>", line 1, in <module>
b = MyClass(3)
File "<pyshell#36>", line 6, in __init__
self.j_var = self.class_var + 1
AttributeError: 'MyClass' object has no attribute 'class_var'
There is no magic here: anything can only exists between its definition point and its destruction point. Python allows you to add attributes to objects at any time, except that some classes (for example object) forbid it.
With the previous a object of class MyClass, you could do:
a.z_var = 12
from that point, z_var will be an attribute of a but others objects of same class will not have it.
Simply object forbids that:
>>> o = object()
>>> o.x=1
Traceback (most recent call last):
File "<pyshell#41>", line 1, in <module>
o.x=1
AttributeError: 'object' object has no attribute 'x'

Do instance variables declared outside of `__init__()` have any differences in python?

I'm wondering weather it is necessary to define class instance variable within class declarations.
I tried assigning a new instance variable after the object (class instance) was already created, and looks like there is no difference. Are there any caveats in this approach?
class Context():
def __init__(self, extension):
self.extension = extension
c = Context('extension+')
print(f"before: {c.__dict__}")
c.new_var = 'new_var_content'
print(c.extension + c.new_var)
print(f"after: {c.__dict__}")
printed:
before: {'extension': 'extension+'}
extension+new_var_content
after: {'extension': 'extension+', 'new_var': 'new_var_content'}
There is no difference between declaring self.foo within a def __init__(self, <arguments>): definition, and declaring it after an object has been instantiated.
Both assignments have instance-level scope.
Given -
class Context:
i_am_a_class_variable = 'class_string'
def __init__(self, bar):
self.bar = bar
See -
class attributes can be accessed without instantiating an object.
>>> Context.i_am_a_class_variable
'class_string'
instance attributes can be assigned during instantiation using the __init__(self) function.
>>> Context.bar
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-4-8be0704da5be> in <module>
----> 1 Context.bar
>>> instance = Context('bar')
>>> instance.bar
'bar'
instance attributes can be assigned after instantiation, directly
>>> instance = Context('bar')
>>> instance.foo = 'foo'
>>> instance.foo
'foo'
Speaking in terms of whether you can assign a value to the property or create a new property, there is no difference if you do it within init or anywhere else after the object is created as in both cases it gets added in dict of the object(unless you use slots)
However, if you want your class to be initialized with desired state (i.e, having some mandatory variables with default/preset values) , you should put it in init. Since init is called implicitly as soon as object is created, you object will be having desired state.

How to know from which class an attribute is coming

Imagine an instance from a classes has an attribute attr. I want to know from where it got that attribute.
Let's consider those 2 cases in Python :
class vehicle():
speed = 5
class flying_machine(vehicle):
density = 1
And
class vehicle():
def __init__(self):
self.speed = 5
class flying_machine(vehicle):
def __init__(self):
super().__init__()
self.density = 1
If you execute the following line of codes :
b = flying_machine()
s = b.speed
s has the value 5. Both cases are different, in the first case, speed is an attribute of the class "vehicle" and in the other case, it's a attribute of an instance of the class "vehicle".
My problem is the same in both case, i want to know from where b got his attribute "speed", I would like to have a function that i could call on b and "speed" and would point me to the place where b.speed was defined.
In my example, it's easy to see where b got its attribute from, but you could imagine classes and subclasses being defined across multiple documents, and having a long inheritance chain. For example :
# doc1.py
class vehicle():
speed = 5
# doc2.py
from doc1.py import *
class flying_machine(vehicle):
density = 1
# doc3.py
from doc2.py import *
class space_machine(flying_machine):
light_speed = 0.5
# main.py
from doc3.py import *
c = space_machine()
In this last case, my c has an attribute speed, and if I want to see where its coming from, i have to go through all previous import, and that's where it would be useful to have a function to show me that c.speed comes from doc1.py .
Generally, I would advise you to use a proper IDE like PyCharm that allows you to Ctrl+click on any attribute and that will navigate you to where that attribute is assigned.
That being said, you can use a class's mro to dynamically extract some information about where attributes may originate by inspecting the instance's and its classes' __dict__ and __slots__:
def lookup(obj, attr):
if attr in obj.__dict__ or attr in obj.__slots__:
print('{}: instance attribute'.format(attr))
klass = next((k for k in obj.__class__.mro()
if '__slots__' in k.__dict__ and attr in k.__slots__),
None)
if klass:
print('but expected for class {}'.format(klass))
else:
for klass in obj.__class__.mro():
if attr in klass.__dict__:
print('{}: class attribute of {}'.format(attr, klass))
You can use this function for arbitrary objects and attributes:
class Vehicle:
speed = 5
class Ugly:
__slots__ = ('look',)
def __init__(self):
self.look = 'terrible'
class Car(Ugly, Vehicle):
def __init__(self):
super().__init__()
self.num_wheels = 4
>>> c = Car()
>>> lookup(c, 'speed')
speed: class attribute of <class '__main__.Vehicle'>
>>> lookup(c, 'num_wheels')
num_wheels: instance attribute
>>> lookup(c, 'look')
look: instance attribute
but expected for class <class '__main__.Ugly'>

Can a particular instance of a class make its own variables in python?

Can a particular instance make its own variable in python, if yes would it be available to other instances of the class?
for eg:
class A():
Var1 = 10
inst1 = A()
inst1.Var1 # will be 10
but can inst1 make it's own variables like Var2 etc and will these Variables be available to other class A instances like inst2?
In other Words, is a variable, which is bound to an instance of a class, accessible to another instance of the same class?
Actually, the most common use case is for instances to have their "own" variables ("data attributes" in Python terminology) which are not shared between instances. The variables x and y below are examples of such "own" variables (every instance of class A gets its own variable x when the constructor is called, and inst1 also gets its own variable y later):
class A():
def __init__(self): # Constructor - called when A is instantiated
self.x = 10 # Creates x for self only (i.e. for each instance in turn)
inst1 = A()
inst1.x = 15 # Changes x for inst1 only
inst1.y = 20 # Creates y for inst1 only
print(inst1.x, inst1.y) # 15 20
inst2 = A()
print(inst2.x) # 10
To dynamically add attributes to a class or instance you can use setattr:
class MyClass(object):
pass
my_instance = MyClass()
# add attribute to class
setattr(MyClass, 'new_attribute', 'added')
# Class now has attribute
print(MyClass.new_attribute == 'added') # True
# Which is also available to instance
print(my_instance.new_attribute == 'added') # True
# Add attribute to instance
setattr(my_instance, 'instance_only', 'yup')
# Instance now has attribute
print(my_instance.instance_only == 'yup') # True
# Class does not have attribute
MyClass.instance_only # Raises AttributeError
# Add attribute to instances class
settatr(type(my_instance), 'instance_only', 'not anymore')
# Now the attribute is available to the class as well
print(MyClass.instance_only == 'not anymore') # True
# New instances will also have the attributes
new_instance = MyClass()
print(new_instance.new_attribute == 'added') # True
If you are not adding them dynamically see #gilch's answer
Even though the actual use may be questionable, you actually can bind new attributes to a class definition in a way that they are available to all instances of that class:
class A(object):
attrib_one = 'VALUE'
def add_class_attrib(self, name, value):
# Bind new attribute to class definition, **not** to self
setattr(A, name, value)
if __name__ == '__main__':
# Instantiate _before_ changing A's class attributes
a = A()
b = A()
# Add a new class attribute using only _one_ instance
a.add_class_attrib('attrib_two', 'OTHER')
# Print attributes of both instances
print([e for e in dir(a) if not e.startswith('__')])
print([e for e in dir(b) if not e.startswith('__')])
# Create new instance _after_ changing A's class attribs
c = A()
# Print attributes of new instance
print([e for e in dir(c) if not e.startswith('__')])
Running this code will print the following:
['add_class_attrib', 'attrib_one', 'attrib_two']
['add_class_attrib', 'attrib_one', 'attrib_two']
['add_class_attrib', 'attrib_one', 'attrib_two']
And you see, that -- even if a class attribute is added to the class definition after an instance of it has been created, the newly created class attribute in fact is available to all other instances of that (changed) class.
It depends on if you set the variable in the class's dict or the instance's dict.
>>> class A:
var = 10
>>> inst1 = A()
>>> inst2 = A()
>>> inst1.var # not in instance, so looked up in class
10
>>> inst2.var
10
>>> inst2.var = 20 # instance attr shadows that from class
>>> inst2.var
20
>>> A.var = 30 # class attr can also be altered
>>> inst1.var
30
>>> inst2.var
20
>>> del inst2.var # deleting instance attr reveals shadowed class attr
>>> inst2.var
30
>>> inst1.var2 = 'spam'
>>> inst2.var2 # new attr was set on inst1, so not available in inst2
Traceback (most recent call last):
File "<pyshell#663>", line 1, in <module>
inst2.var2
AttributeError: 'A' object has no attribute 'var2'
>>> inst1.__class__.var3 = 'eggs' # same as A.var3 = 'eggs'
>>> inst2.var3 # new attr was set on the class, so all instances see it.
'eggs'

Where to set the class members in Python? [duplicate]

Is there any difference at all between these classes besides the name?
class WithClass ():
def __init__(self):
self.value = "Bob"
def my_func(self):
print(self.value)
class WithoutClass ():
value = "Bob"
def my_func(self):
print(self.value)
Does it make any difference if I use or don't use the __init__ method for declaring the variable value?
My main worry is that I'll be using it one way, when that'll cause me further problems down the road.
Variable set outside __init__ belong to the class. They're shared by all instances.
Variables created inside __init__ (and all other method functions) and prefaced with self. belong to the object instance.
Without Self
Create some objects:
class foo(object):
x = 'original class'
c1, c2 = foo(), foo()
I can change the c1 instance, and it will not affect the c2 instance:
c1.x = 'changed instance'
c2.x
>>> 'original class'
But if I change the foo class, all instances of that class will be changed as well:
foo.x = 'changed class'
c2.x
>>> 'changed class'
Please note how Python scoping works here:
c1.x
>>> 'changed instance'
With Self
Changing the class does not affect the instances:
class foo(object):
def __init__(self):
self.x = 'original self'
c1 = foo()
foo.x = 'changed class'
c1.x
>>> 'original self'
I would like to add something to the responses that I read in this thread and this thread (which references this one).
Disclaimer: this remarks come from the experiments I ran
Variables outside __init__:
These are, in fact, static class variables and are, therefore, accesible to all instances of the class.
Variables inside __init__:
The value of these instance variables are only accesible to the instance at hand (through the self reference)
My contribution:
One thing that programmers must consider when using static class variables is that they can be shadowed by instance variables (if you are accessing the static class variables through the self reference).
Explanation:
Previously, I thought that both ways of declaring the variables were exactly the same (silly me), and that was partly because I could access both kind of variables through the self reference. It was now, when I ran into trouble, that I researched the topic and cleared it up.
The problem with accessing static class variables through the
self reference is that it only references the static class variable if there is no instance variable with the same name, and to make things worse, trying to redefine a static class variable through the self reference does not work because an instance variable is created which then shadows the previously-accesible static class variable.
To get around this problem, you should always reference static class variables through the name of the class.
Example:
#!/usr/bin/env python
class Foo:
static_var = 'every instance has access'
def __init__(self,name):
self.instance_var = 'I am %s' % name
def printAll(self):
print 'self.instance_var = %s' % self.instance_var
print 'self.static_var = %s' % self.static_var
print 'Foo.static_var = %s' % Foo.static_var
f1 = Foo('f1')
f1.printAll()
f1.static_var = 'Shadowing static_var'
f1.printAll()
f2 = Foo('f2')
f2.printAll()
Foo.static_var = 'modified class'
f1.printAll()
f2.printAll()
Output:
self.instance_var = I am f1
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = every instance has access
self.instance_var = I am f2
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = modified class
self.instance_var = I am f2
self.static_var = modified class
Foo.static_var = modified class
I hope this is helpful to someone
further to S.Lott's reply, class variables get passed to metaclass new method and can be accessed through the dictionary when a metaclass is defined. So, class variables can be accessed even before classes are created and instantiated.
for example:
class meta(type):
def __new__(cls,name,bases,dicto):
# two chars missing in original of next line ...
if dicto['class_var'] == 'A':
print 'There'
class proxyclass(object):
class_var = 'A'
__metaclass__ = meta
...
...
class User(object):
email = 'none'
firstname = 'none'
lastname = 'none'
def __init__(self, email=None, firstname=None, lastname=None):
self.email = email
self.firstname = firstname
self.lastname = lastname
#classmethod
def print_var(cls, obj):
print ("obj.email obj.firstname obj.lastname")
print(obj.email, obj.firstname, obj.lastname)
print("cls.email cls.firstname cls.lastname")
print(cls.email, cls.firstname, cls.lastname)
u1 = User(email='abc#xyz', firstname='first', lastname='last')
User.print_var(u1)
In the above code, the User class has 3 global variables, each with value 'none'. u1 is the object created by instantiating this class. The method print_var prints the value of class variables of class User and object variables of object u1. In the output shown below, each of the class variables User.email, User.firstname and User.lastname has value 'none', while the object variables u1.email, u1.firstname and u1.lastname have values 'abc#xyz', 'first' and 'last'.
obj.email obj.firstname obj.lastname
('abc#xyz', 'first', 'last')
cls.email cls.firstname cls.lastname
('none', 'none', 'none')
In Python, a class comes with member functions (methods), class variables, attributes/instance variables (and probably class methods too):
class Employee:
# Class Variable
company = "mycompany.com"
def __init__(self, first_name, last_name, position):
# Instance Variables
self._first_name = first_name
self._last_name = last_name
self._position = position
# Member function
def get_full_name(self):
return f"{self._first_name} {self._last_name}"
By creating an instance of the object
my_employee = Employee("John", "Wood", "Software Engineer")
we essentially trigger __init__ that is going to initialise the instance variables of the newly created Employee. This means that _first_name, _last_name and _position are explicit parameters of the specific my_employee instance.
Likewise, member functions return information or change the state of a specific instance.
Now any variable defined outside the constructor __init__ are considered to be class variables. Those variables are shared amongst all the instances of the class.
john = Employee("John", "Wood", "Software Engineer")
bob = Employee("Bob", "Smith", "DevOps Engineer0")
print(john.get_full_name())
print(bob.get_full_name())
print(john.company)
print(bob.company)
>>> John Wood
>>> Bob Smith
>>> mycompany.com
>>> mycompany.com
You can also use class methods in order to change the class variable for all the instances of the class. For example:
#classmethod
def change_my_companys_name(cls, name):
cls.company = name
and now change_my_companys_name()
bob.change_my_companys_name("mynewcompany.com")
will have effect on all the instances of class Employee:
print(bob.company)
print(john.company)
>>> mynewcompany.com
>>> mynewcompany.com
Example code:
class inside:
def __init__(self):
self.l = []
def insert(self, element):
self.l.append(element)
class outside:
l = [] # static variable - the same for all instances
def insert(self, element):
self.l.append(element)
def main():
x = inside()
x.insert(8)
print(x.l) # [8]
y = inside()
print(y.l) # []
# ----------------------------
x = outside()
x.insert(8)
print(x.l) # [8]
y = outside()
print(y.l) # [8] # here is the difference
if __name__ == '__main__':
main()
This is very easy to understand if you track class and instance dictionaries.
class C:
one = 42
def __init__(self,val):
self.two=val
ci=C(50)
print(ci.__dict__)
print(C.__dict__)
The result will be like this:
{'two': 50}
{'__module__': '__main__', 'one': 42, '__init__': <function C.__init__ at 0x00000213069BF6A8>, '__dict__': <attribute '__dict__' of 'C' objects>, '__weakref__': <attribute '__weakref__' of 'C' objects>, '__doc__': None}
Note I set the full results in here but what is important that the instance ci dict will be just {'two': 50}, and class dictionary will have the 'one': 42 key value pair inside.
This is all you should know about that specific variables.
classes are like blueprints to create objects. Let's make a metaphor with building a house. You have the blueprint of the house so you can build a house. You can build as many houses as your resources allow.
In this metaphor, the blueprint is the class and the house is the instantiation of the class, creating an object.
The houses have common attributes like having a roof, living room, etc. This is where you init method goes. It constructs the object (house) with the attributes you want.
Lets suppose you have:
`class house:`
`roof = True`
`def __init__(self, color):`
`self.wallcolor = color`
>> create little goldlock's house:
>> goldlock = house() #() invoke's class house, not function
>> goldlock.roof
>> True
all house's have roofs, now let's define goldlock's wall color to white:
>> goldlock.wallcolor = 'white'
>>goldlock.wallcolor
>> 'white'
class foo(object):
mStatic = 12
def __init__(self):
self.x = "OBj"
Considering that foo has no access to x at all (FACT)
the conflict now is in accessing mStatic by an instance or directly by the class .
think of it in the terms of Python's memory management :
12 value is on the memory and the name mStatic (which accessible from the class)
points to it .
c1, c2 = foo(), foo()
this line makes two instances , which includes the name mStatic that points to the value 12 (till now) .
foo.mStatic = 99
this makes mStatic name pointing to a new place in the memory which has the value 99 inside it .
and because the (babies) c1 , c2 are still following (daddy) foo , they has the same name (c1.mStatic & c2.mStatic ) pointing to the same new value .
but once each baby decides to walk alone , things differs :
c1.mStatic ="c1 Control"
c2.mStatic ="c2 Control"
from now and later , each one in that family (c1,c2,foo) has its mStatica pointing to different value .
[Please, try use id() function for all of(c1,c2,foo) in different sates that we talked about , i think it will make things better ]
and this is how our real life goes . sons inherit some beliefs from their father and these beliefs still identical to father's ones until sons decide to change it .
HOPE IT WILL HELP
As noted by S.Lott,
Variable set outside init belong to the class. They're shared by
all instances.
Variables created inside init (and all other method functions) and
prefaced with self. belong to the object instance.
However,
Note that class variables can be accessed via self.<var> until they are masked by an object variable with a similar name This means that reading self.<var> before assigning it a value will return the value of Class.<var> but afterwards it will return obj.<var> . Here is an example
In [20]: class MyClass:
...: elem = 123
...:
...: def update(self,i):
...: self.elem=i
...: def print(self):
...: print (MyClass.elem, self.elem)
...:
...: c1 = MyClass()
...: c2 = MyClass()
...: c1.print()
...: c2.print()
123 123
123 123
In [21]: c1.update(1)
...: c2.update(42)
...: c1.print()
...: c2.print()
123 1
123 42
In [22]: MyClass.elem=22
...: c1.print()
...: c2.print()
22 1
22 42
Second note: Consider slots. They may offer a better way to implement object variables.
Try this and check the difference
class test:
f = 3
def __init__(s, f):
s.__class__.f = f
s.f = s.__class__.f
print(f'def __init__(s, {f})')
print(f's.__class__.f = {f}')
print(f's.f={s.__class__.f}')
print(f'f={f}')
print('===============init over===========')
def setinstancetoOne(s, f):
print(f'def setinstancetoOne(s, {f})')
s.f = f
print(f'class var f = {f}')
def useClassname(test):
print(f'>>>>def useClassname({test})')
print(f'test.f {test.f}')
def p_method(s):
print(f'>>>>def p_method({s})')
print(f's.f {s.f}')
print(f'test.f {test.f}')
print(f's.__class__.f {s.__class__.f}')
print(f'class var f={f}')
# test.__init__.f = 19
t = test(2)
t.useClassname()
t.p_method()
print(f'Outside class t.f {t.f}')
print(f'Outside class test.f {test.f}')
print('______difference__________')
t = test(2)
t.setinstancetoOne(1)
t.useClass()
t.p_method()
print(f'Outside class instance variable(2) {t.f}')
print(f'Outside class class variable(3) {test.f}')

Categories