class Point():
'''Create a Point'''
my_name = 'A Point'
def __init__(self, x, y):
self.x = x
self.y = y1 类和对象的__dict__属性
1.1 对象的__dict__属性
p = Point(3, 4)
p.__dict__{'x': 3, 'y': 4}
对象的__dict__属性就是一个字典,这个字典的键是对象的属性,值就是对应属性的值。
当给对象属性复制的时候,就是修改__dict__字典。
1.2 类的__dict__属性
Point.__dict__mappingproxy({'__module__': '__main__',
'__doc__': 'Create a Point',
'my_name': 'A Point',
'__init__': <function __main__.Point.__init__(self, x, y)>,
'__dict__': <attribute '__dict__' of 'Point' objects>,
'__weakref__': <attribute '__weakref__' of 'Point' objects>})
可以看到,Point类的__dict__属性包括了:
- 类的文档
__doc__ - 类中定义变量,比如这里的
my_name - 类的方法
- 其他一些不知道什么的东西😓
2 类的__repr__和__str__方法
2.1 __repr__方法
直接输出p时,会显示一堆没用的东西
p<__main__.Point at 0x10d4f4eb0>
我们想显示关于Point的有用信息,这时__repr__方法就派上用场了
class Point():
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return "Point(x=%r, y=%r)" % (self.x, self.y)p = Point(3, 4)
pPoint(x=3, y=4)
2.2 __str__方法
__str__方法和__repr__方法好像都是用字符表示对象的,有什么区别呢?
stackoverflow有一个回答说:
__repr__显示的信息需要避免歧义__str__显示的信息注重可读性,方便理解__str__使用了__repr
str(p)'Point(x=3, y=4)'
在Point中如果没有重写__str__方法,会调用__repr__输出的结果
如果在Point中重写了__str__方法,就会输出__str__调用的结果。
class Point():
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return "Point(x=%r, y=%r)" % (self.x, self.y)
def __str__(self):
return f'Just a normal 2d point({self.x}, {self.y})'p = Point(3, 4)pPoint(x=3, y=4)
repr(p)'Point(x=3, y=4)'
print(p)Just a normal 2d point(3, 4)
str(p)'Just a normal 2d point(3, 4)'
3 类的__setattr__方法
p = Point('3', '4')
pPoint(x='3', y='4')
想在初始化Point的时候,把x,y属性转变成float类型,__setattr__方法就能用上了
class Point():
def __init__(self, x, y):
self.x = x
self.y = y
def __setattr__(self, name, value):
self.__dict__[name] = float(value)
def __repr__(self):
return "Point(x=%r, y=%r)" % (self.x, self.y)p = Point('3', '4')
pPoint(x=3.0, y=4.0)
p.__dict__p的x和y属性都已经是float类型了,这是怎么做到的呢?
在类的__init__函数中,self.x =x这一句,self.x的值设为x,
当遇到这种对象.属性 = 值的时候,如果重写了__setattr__方法,就会调用__setattr__方法,
也就是说当遇到对象.属性 = 值,相当于调用了__setattr__(对象, 属性, 值)
在这里相当于__setattr__(self, 'x', x),在__setattr__函数里修改了self.__dict__['x'] = float(value)
__setattr__函数里面可以做你想做的任何事情,不仅仅是改变默认的属性赋值操作
class Point():
def __init__(self, x, y):
self._modules = {}
self.x = x
self.y = y
def __setattr__(self, name, value):
if not name.startswith('_'):
self._modules[name] = value
print(f'add {name}:{value} to _module')
print(f'set {name} to {value}')
super().__setattr__(name, value)
def __repr__(self):
return "Point(x=%r, y=%r)" % (self.x, self.y)p = Point(3, 4)set _modules to {}
add x:3 to _module
set x to 3
add y:4 to _module
set y to 4
p._modules{'x': 3, 'y': 4}