文章目录
1、__init__
和__call__
__init__
将被视为构造函数,而__call__
方法可以被对象任意多次调用。
__init__
和__call__
函数都接受默认参数。
class Counter:
def __init__(self):
self._weights = []
for i in range(0, 2):
self._weights.append(1)
print(str(self._weights[-2]) + " No. from __init__")
def __call__(self, t):
self._weights = [self._weights[-1], self._weights[-1]
+ self._weights[-1]]
print(str(self._weights[-1]) + " No. from __call__")
num_count = Counter()
for i in range(0, 4):
num_count(i)
输出
1 No. from __init__
2 No. from __call__
4 No. from __call__
8 No. from __call__
16 No. from __call__
2、__init__
和__new__
当你需要控制新实例的创建的时候,使用__new__
。
当你需要控制一个新实例的初始化的时候,使用__init__
。
class Shape:
def __new__(cls, sides, *args, **kwargs):
if sides == 3:
return Triangle(*args, **kwargs)
else:
return Square(*args, **kwargs)
class Triangle:
def __init__(self, base, height):
self.base = base
self.height = height
def area(self):
return (self.base * self.height) / 2
class Square:
def __init__(self, length):
self.length = length
def area(self):
return self.length * self.length
a = Shape(sides=3, base=2, height=12)
b = Shape(sides=4, length=2)
print(str(a.__class__))
print(a.area())
print(str(b.__class__))
print(b.area())
输出
<class '__main__.Triangle'>
12.0
<class '__main__.Square'>
4
3、__getattr__
和__setattr__
__getattr__
方法拦截属性引用(attribute references),__setattr__
方法拦截所有属性赋值(attribute assignments)。
class Employee(object):
def __init__(self, data):
super().__setattr__('data', dict())
self.data = data
print("这是初始化赋值", data)
def __getattr__(self, name):
if name in self.data:
print("当key在data中的时候,直接取值")
return self.data[name]
else:
print("当key不在data中的时候,直接返回0")
return 0
def __setattr__(self, key, value):
if key in self.data:
self.data[key] = value
print("当key在data中时, 重新赋值即可", self.data[key])
else:
super().__setattr__(key, value)
print("当key不在data中时")
emp = Employee({'age': 23, 'name': 'John'})
print(emp.age)
print(emp.name)
print(emp.data)
print(emp.salary)
emp.name = "Fuck"
print(emp.name)
emp.salary = 50000
print(emp.salary)
输出
当key不在data中时
这是初始化赋值 {'age': 23, 'name': 'John'}
当key在data中的时候,直接取值
23
当key在data中的时候,直接取值
John
{'age': 23, 'name': 'John'}
当key不在data中的时候,直接返回0
0
当key在data中时, 重新赋值即可 Fuck
当key在data中的时候,直接取值
Fuck
当key不在data中时
50000
4、@staticmethod和@classmethod
我们知道一般来说要使用某个类的方法,都需要先实例化一个对象再调用相应的方法。
而通过使用@staticmethod
或者@classmethod
,就可以不需要实例化,直接使用类名.方法名()
来调用。
这样将会有利于组织代码,把某些应该属于某个类的函数给放到那个类里面去,同时有利于命名空间的整洁。
那么@staticmethod
和classmethod
的区别是什么呢?
从使用上来看,
- @staticmethod不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样。
- @classmethod不需要self参数,但是第一个参数需要是表示自身类的cls参数。
如果在@staticmethod
中要调用到这个类的一些属性方法,只能直接通过类名.属性名
或者类名.方法名
来调用。
而@classmethod
因为持有cls
参数,可以用来调用类的属性、类的方法、实例化对象等,从而避免硬编码。