When I was making a summary that also served as a memorandum at here, I noticed or discovered it again, so I would like to describe it here.
A sample that outputs "Hello World". Define the class variable c_var
and the instance variable ʻi_var` respectively.
class Test(object):
c_var = "Hello"
def __init__(self):
self.i_var = "World"
def __str__(self):
return Test.c_var + " " + self.i_var
print(Test())
Validate with a pattern that defines an instance variable with the same name as a class variable (ʻexamine1) and a pattern that modifies a class variable (ʻexamine2
).
class Test(object):
c_var = "Hello"
def __init__(self):
self.i_var = "World"
def __str__(self):
return Test.c_var + " " + self.i_var
def examine1(self):
self.c_var = "Hey"
return self
def examine2(self):
Test.c_var = "Hey"
return self
t = Test()
print(t.examine1())
print(t.examine2())
print(Test())
From the output result, it can be seen that the class variable and the instance variable are different, and the instance variable can be changed.
Output result
Hello World
Hey World
Hey World
You can check instance variables with vars (t)
and class variables with vars (Test)
.
Now try changing the class variables with class methods and static methods instead of methods. From the output result, both __init__
are called and the class variables are changed.
class Test(object):
c_var = "Hello"
def __init__(self):
self.i_var = "World"
def __str__(self):
return Test.c_var + " " + self.i_var
@classmethod
def class_method(cls):
cls.c_var = "Class"
@staticmethod
def static_method():
Test.c_var = "Static"
Test.class_method()
print(Test())
Test.static_method()
print(Test())
Output result
Class World
Static World
Now let's examine the changes in class variables and instance variables when making shallow and deep copies. The value of the class variable is changed even in the deep copy.
import copy
class Test(object):
c_var = 2
def __init__(self, obj):
self.i_var = obj
def __str__(self):
return "{0} {1}".format(Test.c_var, self.i_var)
def examine1(self):
self.i_var += 2
return self
def examine2(self):
Test.c_var += 2
return self
a = int(3)
t1 = Test(a)
t1.examine1().examine2()
print(t1)
print(Test(a))
print("--- shallow copy ---")
t2 = copy.copy(t1)
t2.examine1().examine2()
print(t1)
print(t2)
print(Test(a))
print("--- deep copy ---")
t3 = copy.deepcopy(t1)
t3.examine1().examine2()
print(t1)
print(t2)
print(t3)
print(Test(a))
Output result
4 5
4 3
--- shallow copy ---
6 5
6 7
6 3
--- deep copy ---
8 5
8 7
8 7
8 3
self
A class that defines two methods, ʻexamine1 and ʻexamine2
.
class Test(object):
def __init__(self):
self.i_var = "nothing"
def __str__(self):
return self.i_var
def examine1(self):
self.i_var = "examine1"
return self
def examine2(self):
self.i_var = "examine2"
return self
t1 = Test()
print(t1)
print(t1.examine1())
print(t1.examine2())
The output result is as follows.
Output result
nothing
examine1
examine2
Here, when I executed print (Test.examin1 ())
like a class method, of course I got an error.
error
examine1() missing 1 required positional argument: 'self'
So is it possible to specify an instance in the first argument self
?
t1 = Test()
print(Test.examine1(t1.examine2()))
print(Test.examine2(t1.examine1()))
When the above was executed, the following result was output.
Output result
examine1
examine2
Summary presented me with a callable class, and at the same time I was keenly aware of my lack of study.
class Callable(int):
def __call__(self, *arguments):
print(arguments[0])
a = Callable(5)
print(a)
a(3)
Output result
5
3
The above means that ʻacan be used both as a function and as a variable. Since the reference value of the
Callable instance is assigned to ʻa
, the value passed as an argument at the time of instance creation is displayed byprint (a)
. Also, when ʻa is called like a function,
callis called, so the value of the first argument is
print`.
Implementation that extends ʻint to callable and handles the first argument as a unit (name) in a function call. Replacing the standard ʻint
class with ʻint = Callable`.
class Callable(int):
def __call__(self, unit):
print("{0} {1}".format(self, unit))
int = Callable
print(int("3") * 4)
int("5")("meters")
int(2017 - 2010)("years old")
12
5 meters
7 years old
We have prepared a class that implements __add__
and __sub__
. The reference value does not change even if it is added or subtracted as shown below. This also replaced the standard ʻint. The value of ʻid
did not change after the replacement.
class MyInt(object):
def __init__(self, v):
self.__v = v
def __add__(self, other):
self.__v += other
return self
def __sub__(self, other):
self.__v -= other
return self
a = int(2)
print(id(a))
a = a + 3
print(id(a))
a = a - 5
print(id(a))
int = MyInt
a = int(3)
print(id(a))
a = a + 3
print(id(a))
a = a - 5
print(id(a))
1983644176
1983644272
1983644112
1736248227544
1736248227544
1736248227544
__mul__
, __matmul__
, __truediv__
, __floordiv__
, __mod__
, __divmod__
, __pow__
, __lshift__
, __rshift__
, __and__
, `_xor Implement accordingly.
I used ʻint` in the verification of class variables and instance variables (3), but I tried to verify using the mutable numerical object defined here. As with immutables, class variables can be changed in value even with deep copies.
import copy
class MyInt(object):
def __init__(self, v):
self.__v = v
def __str__(self):
return str(self.__v)
def __add__(self, other):
self.__v += other
return self
def __sub__(self, other):
self.__v -= other
return self
int = MyInt
class Test(object):
c_var = int(2)
def __init__(self, obj):
self.i_var = obj
def __str__(self):
return "{0} {1}".format(Test.c_var, self.i_var)
def examine1(self):
self.i_var += 2
return self
def examine2(self):
Test.c_var += 2
return self
a = int(3)
t1 = Test(a)
t1.examine1().examine2()
print(t1)
print(Test(a))
print("--- shallow copy ---")
t2 = copy.copy(t1)
t2.examine1().examine2()
print(t1)
print(t2)
print(Test(a))
print("--- deep copy ---")
t3 = copy.deepcopy(t1)
t3.examine1().examine2()
print(t1)
print(t2)
print(t3)
print(Test(a))
Output result
4 5
4 5
--- shallow copy ---
6 7
6 7
6 7
--- deep copy ---
8 7
8 7
8 9
8 7
Recommended Posts