class Point():
'''Create a Point'''
= 'A Point'
my_name def __init__(self, x, y):
self.x = x
self.y = y
1 类和对象的__dict__
属性
1.1 对象的__dict__
属性
= Point(3, 4)
p 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)
= Point(3, 4)
p p
Point(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})'
= Point(3, 4) p
p
Point(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__
方法
= Point('3', '4')
p p
Point(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)
= Point('3', '4')
p p
Point(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)
= Point(3, 4) p
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}