类和对象
类的构造方法 def __init__():
1 class People:
2 def __init__(self,name):
3 self.name = name
注意:在构造方法中的变量不用再次声明,必须有self,创建类的对象是用=
类的私有成员
让方法或者类变为私有,只要在它的名字前加上双下划线
1 class People:
2 __name = 'laowang'
3 def getname(self):
4 return self.__name
注意:类的私有成员可以通过方法访问,也可以通过 _类名__私有成员这种格式来访问
类的继承
class 子类(父类、基类、超类)
在继承构造函数的过程中,可以用以下两个方法,推荐方法2:
(1)调用未绑定的父类构造方法
1 class People:
2 def __init__(self):
3 self.name = 'aa'
4 class Student(People):
5 def __init__(self):
6 People.__init__(self)
7 self.son = 20
(2)使用super
class People:
def __init__(self):
self.name = 'aa'
class Student(People):
def __init__(self):
super().__init__()
self.son = 20
super可以不带任何参数,但是当父类中有参数传入,super后的__init__要加上参数而且不能加上self
1 class People:
2 def __init__(self,name):
3 self.name = name
4 class Student(People):
5 def __init__(self,name,sno):
6 super().__init__(name)
7 self.name = name
8 self.sno = sno
类的组合
类之间没用明显继承关系可以用组合,比如一个电话簿的类由电话和地址类组合起来:
1 class Tel:
2 def __init__(self,x):
3 self.info = x
4
5 class Add:
6 def __init__(self,y):
7 self.info = y
8
9 class Notebook:
10 def __init__(self,x,y):
11 self.tel = Tel(x)
12 self.add = Add(y)
13 def print_info(self):
14 print("Tel:%s
Add:%s" %(self.tel.info,self.add.info))
类 类对象 实例对象
类对象就像C++中的static变量,一个对象有了实例对象后就将类对象的值覆盖了
属性名如果和方法名相同,属性会覆盖方法
绑定
对象.__dict__返回对象拥有的属性
对象调用后方法绑定到实例对象上del类后,a的方法还是存在的,因为A的方法和属性都是static,程序退出前不会消失
一些和类相关的BIF
issubclass(class, classinfo)
isinstance(object, classinfo)
hasattr(object, name) 注意第二个参数要用字符串格式
getattr(object, name[, default])
setattr(object, name, value) 设置属性
delattr(object, name) 删除属性,属性不存在抛出异常
property()
为什么用property
首先一个实例化的对象可以进行直接的赋值和修改,如c.age = 10,但是这样没法做参数检查,我就可以让c.age = 1000,这显然是不合理的
于是,用方法可以对参数进行检查,可以用c.setage(66)来设置年龄,但是这样就不方便了
函数property的基本功能就是把类中的方法当作属性来访问,为什么用方法来操作
1 class C: 2 def __init__(self,age = 10): 3 self.age = age 4 def getage(self): 5 return self.age 6 def setage(self,value): 7 if 0 <= value <= 120: 8 self.age = value 9 else: 10 print("年龄非法") 11 def delage(self): 12 del self.age 13 x = property(getage,setage,delage)
魔法方法
(1)构造和析构
魔法方法总是被双下划线包围,它们总能在适当的时候自动被调用
__init__(self) 不能有返回值
__new__(cls[,]) 返回一个类对象,python自动调用,一般不需要重写,依照Python官方文档的说法,__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。
__del__(self) del一个对象的时候被调用
(2)属性和访问
__getattr__(self,name) 定义当用户试图获取一个不存在的属性时的行为
__getattribute__(self,name) 定义当该类属性被访问时的行为
__setattr__(self,name,value) 定义当一个属性被设置的行为
__delattr__(self,name) 定义当一个属性被删除的行为
程序1:查看属性方法何时被调用
1 class C: 2 def __getattribute__(self,name): 3 print("getattribute") 4 return super().__getattribute__(name) 5 def __getattr__(self,name): 6 print("getattr") 7 def __setattr__(self,name,value): 8 print("setattr") 9 super().__setattr__(name,value) 10 def __delattr__(self,name): 11 print("delattr") 12 super().__delattr__(name)
当访问一个不存在的属性,就调用先调用getattribute,在调用getattr,访问存在的属性调用getattribut后显示其值
程序2:写一个矩形类,默认有宽高两个属性,如果给一个叫square的属性复制,那么说明这是一个正方形(Python基础教程151,小甲鱼45)
1 class Rectangle: 2 def __init__(self,width = 0,height = 0): 3 self.width = width 4 self.height = height 5 def __setattr__(self,name,value): 6 if name == "square": 7 self.width = value 8 self.height = value 9 else: 10 self.__dict__[name] = value 11 def getarea(self): 12 return self.width * self.height
(3)描述符(property的原理)
描述符就是将某种特殊类型的类的实例指派给另一个类的属性
__get__(self,instance,owner) 用于访问属性,它返回属性的值
__set__(self,instance,value) 将在属性分配操作中调用,不返回任何内容
__delete__(self,instance) 控制删除操作,不返回任何内容
(4)定制容器(Python基础教程144,小甲鱼47)
定制的容器对象是不可变的,需要前两个魔法方法;可变的需要4个魔法方法
1. 如果说你希望定制的容器是不可变的话,你只需要定义 __len__() 和 __getitem__() 方法。
2. 如果你希望定制的容器是可变的话,除了 __len__() 和 __getitem__() 方法,你还需要定义 __setitem__() 和__delitem__() 两个方法。
迭代器
BIF:iter()返回一个迭代器,next()返回下一个元素
对应的魔法方法__iter__() __next__()
用迭代器写的裴波那切数列:
1 class Fibs: 2 def __init__(self,n = 10): 3 self.a = 0 4 self.b = 1 5 self.n = n 6 def __iter__(self): 7 return self 8 def __next__(self): 9 self.a,self.b = self.b,self.a+self.b 10 if self.a > self.n: 11 raise StopIteration 12 return self.a
生成器
生成器是迭代器的一种实现
用yield或者圆括号
yield
圆括号