len方法
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __len__(self):
return 5
person = Person("小贵", 25)
print(len(person))
输出
5
hash方法
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __len__(self):
return 5
def __hash__(self):
return 55555
person = Person("小贵", 25)
print("-----len-----")
print(len(person))
print("-----hash-----")
print(hash(person))
输出
-----len-----
5
-----hash-----
55555
eq方法
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __len__(self):
return 5
def __hash__(self):
return 55555
def __eq__(self, other):
return True
person = Person("小贵", 25)
print("-----len-----")
print(len(person))
print("-----hash-----")
print(hash(person))
print("-----eq-----")
print(person.__eq__("你好"))
输出
-----len-----
5
-----hash-----
55555
-----eq-----
True
item系列
可以把一个对象变成dict, 可以像dict一样增删改查
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
names = {"name": "小龟龟"}
def __getitem__(self, item):
return Person.names[item]
def __setitem__(self, key, value):
Person.names[key] = value
def __delitem__(self, key):
Person.names.pop(key)
person = Person("小贵", 25)
print("-----getitem-----")
print(person["name"])
print("-----setitem-----")
person["age"] = 20
print(Person.names)
print("-----delitem-----")
del person["age"]
print(Person.names)
输出
-----getitem-----
小龟龟
-----setitem-----
{'name': '小龟龟', 'age': 20}
-----delitem-----
{'name': '小龟龟'}
str & repr
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return "Person %s %s" % (self.name, self.age)
def __str__(self):
return "%s %s" % (self.name, self.age)
person = Person("小贵", 25)
# repr&str
print("-----repr&str-----")
'''
str函数或者print函数调用时--->obj.__str__()
repr或者交互式解释器中调用时--->obj.__repr__()
如果__str__没有被定义,那么就会使用__repr__来代替输出
注意:这俩方法的返回值必须是字符串,否则抛出异常
'''
print(repr(person), person.__repr__())
print(str(person), person.__str__(), person)
输出
Person 小贵 25 Person 小贵 25
小贵 25 小贵 25 小贵 25
del 析构方法
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return "Person %s %s" % (self.name, self.age)
def __str__(self):
return "%s %s" % (self.name, self.age)
def __del__(self):
print("销毁对象(析构)...")
person = Person("小贵", 25)
# repr&str
print("-----repr&str-----")
print(repr(person), person.__repr__())
print(str(person), person.__str__(), person)
print("-----del(析构)-----")
# 析构方法
del person
输出
-----repr&str-----
Person 小贵 25 Person 小贵 25
小贵 25 小贵 25 小贵 25
-----del(析构)-----
销毁对象(析构)...
new方法
使用
我们知道实例化init会自动执行, 其实在init方法之前,还有一个new方法也会自动执行,你可以在new里执行一些实例化前的定制动作
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
print("init")
def __new__(cls, *args, **kwargs):
print(cls, args, kwargs)
person = Person("小贵", 15)
输出
<class '__main__.Person'> ('小贵', 15) {}
为什么init没有执行?
因为init方法是由new方法调用的,我们重写了new方法,此时并没有执行init方法
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
print("init")
def __new__(cls, *args, **kwargs):
print(cls, args, kwargs)
return super().__new__(cls)
person = Person("小贵", 15)
输出
<class '__main__.Person'> ('小贵', 15) {}
init
用new方法实现单例模式
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。**通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,**从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
什么情况下用单例?
对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID(序号)生成器。如在Windows中就只能打开一个任务管理器。如果不使用机制对窗口对象进行唯一化,将弹出多个窗口,如果这些窗口显示的内容完全一致,则是重复对象,浪费内存资源;如果这些窗口显示的内容不一致,则意味着在某一瞬间系统有多个状态,与实际不符,也会给用户带来误解,不知道哪一个才是真实的状态。因此有时确保系统中某个对象的唯一性即一个类只能有一个实例非常重要
如何保证一个类只有一个实例并且这个实例易于被访问呢?定义一个全局变量可以确保对象随时都可以被访问,但不能防止我们实例化多个对象。一个更好的解决办法是让类自身负责保存它的唯一实例。这个类可以保证没有其他实例被创建,并且它可以提供一个访问该实例的方法。这就是单例模式的模式动机。
class Person:
instance = None
def __init__(self, name, age):
self.name = name
self.age = age
print("init")
def __new__(cls, *args, **kwargs):
if cls.instance is None:
instance = super().__new__(cls)
cls.instance = instance
return cls.instance
person1 = Person("小贵", 15)
person2 = Person("小贵", 15)
person3 = Person("小贵", 15)
person4 = Person("小贵", 15)
print(id(person1))
print(id(person2))
print(id(person3))
print(id(person4))
输出
init
init
init
init
1260870865056
1260870865056
1260870865056
1260870865056
call方法
对象后面加括号,触发执行。
注:构造方法new的执行是由创建对象触发的,即:对象 = 类名() ;而对于 call 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class School:
def __init__(self, name):
self.name = name
def __call__(self, *args, **kwargs):
print(self, args, kwargs)
school = School("呼呼呼")
school("好学校", flag="世界一流")
输出
<__main__.School object at 0x0000029FB38A8460> ('好学校',) {'flag': '世界一流'}