目录:
新式类和经典类的区别:
1)首先,写法不一样:
class A: #经典类写法
pass
class B(object): #新式类写法
pass
2)多继承中,新式类采用广度优先搜索,而旧式类是采用深度优先搜索,python3中全是广度优先
3)在继承中新式类和经典类写法区别
SchoolMember.__init__(self,name,age,sex) #经典类写法
super(Teacher,self).__init__(name,age,sex) #新式类写法
代码展示
class D:
def talk(self):
print('D')
class B(D):
pass
# def talk(self):
# print('B')
class C(D):
pass
def talk(self):
print('C')
class A(B,C):
pass
# def talk(self):
# print('A')
a = A()
a.talk()
重写特殊的构造方法
- 注:如果一个类的构造方法被重写,那么就需要调用超类的构造方法,否则对象可能不能给被正确的初始化
- 其实调用超类构造方法很容易,SongBird类中只添加一行代码
python 经典类写法: Bird.__init__(self)
新式类写法: super(SongBird,self).__init__()
- 如果将下面代码没有2中的那句调用父类Bird中的self.hungry方法会报错
if self.hungry == True:
AttributeError: SongBird instance has no attribute 'hungry'
新式类,经典类,无超类构造方法报错
class Bird:
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry == True:
print("Aaaah...")
self.hungry = False
else:
print("no, thanks")
a = Bird()
a.eat()
a.eat()
class SongBird(Bird):
def __init__(self):
# Bird.__init__(self) # 经典类写法
# super(SongBird,self).__init__() # 新式类写法
self.sound = 'Squawk'
def sing(self):
print(self.sound)
b = SongBird()
b.sing()
b.eat()
类的特殊方法
__doc__ 表示类的描述信息
class Foo:
""" 输出类的描述类信息 """
def func(self):
pass
print(Foo.__doc__) #运行结果:描输出类的描述类信息
__call__ 对象后面加括号,触发执行
- 作用:构造方法__init__的执行是由创建对象触发的,即:对象 = 类名()
- 对于 call 方法的执行是由对象后,括号触发的,即:对象() 或者 类()()
执行__call__方法
class Dog(object):
def __init__(self,name):
self.name = '实例变量'
self.name = name
def __call__(self, *args, **kwargs):
print("running call")
print(args,kwargs)
d = Dog("ChenRonghua")
d(name='tom') # 如果只实例化,而不d()调用,__call__函数不会执行
# 运行结果:
# running call
# () {'name': 'tom'}
__str__ 如果一个类中定义了__str__方法,在打印对象时,默认输出该方法的返回值**
class Foo:
def __str__(self):
return 'alex li'
obj = Foo()
print(obj) # 输出:alex li
__dict__ 查看类或对象中的所有成员
class Province:
country = 'China'
def __init__(self, name, count):
self.name = name
self.count = count
def func(self, *args, **kwargs):
print('func')
# 获取类的成员,即:静态字段、方法、
print(Province.__dict__)
# 输出:{'country': 'China', '__module__': '__main__', 'func': <function func at 0x10be30f50>, '__init__': <function __init__ at 0x10be30ed8>, '__doc__': None}
obj1 = Province('HeBei',10000)
print(obj1.__dict__)
# 获取 对象obj1 的成员
# 输出:{'count': 10000, 'name': 'HeBei'}
obj2 = Province('HeNan', 3888)
print(obj2.__dict__)
# 获取 对象obj1 的成员
# 输出:{'count': 3888, 'name': 'HeNan'}
_getitem__、__setitem__、__delitem__ 作用:用于索引操作,如字典。以上分别表示获取、设置、删除数据
class Foo(object):
def __getitem__(self, key):
print('__getitem__', key)
def __setitem__(self, key, value):
print('__setitem__', key, value)
def __delitem__(self, key):
print('__delitem__', key)
obj = Foo()
result = obj['k1'] # __getitem__ k1
obj['k2'] = 'wupeiqi' # __setitem__ k2 wupeiqi
del obj['k1'] # __delitem__ k1
__new__ \ __metaclass__ 作用: __metaclass__定义这个类以怎样的形式被创建
class User(object):
def __init__(self,name,age):
print('__init__')
def __new__(cls, *args, **kwargs):
print("__new__",args,kwargs)
return object.__new__(cls) # 调用一下object的__new__方法否则不往下走
d = User('tom',100)
# 运行结果:
# __new__ ('tom', 100) {}
# __init__
__new__和__init__的区别
- __new__是一个静态方法,而__init__是一个实例方法.
- __new__方法会返回一个创建的实例,而__init__什么都不返回.
- 只有在__new__返回一个cls的实例时后面的__init__才能被调用.
- 当创建一个新实例时调用__new__,初始化一个实例时用__init__.
type生成类调用顺序
- new : 先于__init__方法,每生成一个实例执行一次
- init : __init__方法每生成一个实例对象就会执行一次
- call : 后与__init__方法,C()() 使用类再加一个括号调用, C为类名称
- del : 析构方法,删除无用的内存对象(当程序结束会自动自行析构方法)
class Student(object):
def __new__(cls, *args, **kwargs):
print('__new__')
return object.__new__(cls) # 必须返回父类的__new__方法,否则不不执行__init__方法,无法创建实例
def __init__(self,name):
print('__init__')
self.name = name
def __str__(self): # 作用:打印实例时显示指定字符串,而不是内存地址
print('__str__')
return self.name
def __call__(self, *args, **kwargs): # 当执行C()(*args) 或者 s1(*args) 就会执行__call__
print('__call__',*args)
def __del__(self): # 作用:清除无用的实例对内存的暂用
print('__del__')
#1、实例化时机会执行__new__、__init__
s1 = Student('tom')
#2、执行 实例() 就会执行__call__ 方法,并将参数传递给__call__函数
s1('call01')
#3、当打印实例时就会执行 __str__ 方法下返回的字符串(默认返回的实例地址)
print(s1)
#4、析构方法:当删除实例时就会调用 __del__ 方法
del s1
# 析构方法作用:在程序结束后会自动执行析构方法删除所有实例
# 但是在程序运行时有很多实例是无用的,但是python内存回收机制却不会自动删除他们,这样就浪费内存
# 我们可以执行 del s1 ,那么在程序运行时,python内存回收机制会检测到这些实例时无用的,才会删除
# 其实我们执行del s1,并没有回收内存,只不过是摘除门牌号,python内存回收机制发现没有门牌号后会自动回收内存
单例模式原理及作用
- 单例模式:永远用一个对象得实例,避免新建太多实例浪费资源
- 实质:使用__new__方法新建类对象时先判断是否已经建立过,如果建过就使用已有的对象
- 使用场景:如果每个对象内部封装的值都相同就可以用单例模式
创建单例模式举例
class Foo(object):
instance = None
def __init__(self):
self.name = 'alex'
def __new__(cls, *args, **kwargs):
if Foo.instance:
return Foo.instance
else:
Foo.instance = object.__new__(cls,*args,**kwargs)
return Foo.instance
obj1 = Foo() # obj1和obj2获取的就是__new__方法返回的内容
obj2 = Foo()
print(obj1,obj2) # 运行结果: <__main__.Foo object at 0x00D3B450> <__main__.Foo object at 0x00D3B450>
# 运行结果说明:
# 这可以看到我们新建的两个Foo()对象内存地址相同,说明使用的•同一个类,没有重复建立类