类
属性
实例变量: __init__需要初始化的变量,实例变量作用域就是实例本身
类变量: 写在class全局的变量
私有属性 ,如下:这样的话通过实例无法调用这个属性 。
当要访问私有属性的时候,可以新建一个方法,内部方法是可以调用私有属性的,然后通过调用这个方法来获取私有属性的值:
print(r1.show_status())
如果实例调用变量,实例变量和类变量都定义了相同变量,那么优先去实例变量,没有再找类变量。
方法
构造方法:
def __init__(self):
self.name = name
析构函数,在实例释放(删除实例del 或者实例运行结束),销毁的时候自动执行的,通常做一些收尾工作。如:关闭一些数据库链接,关闭打开的临时文件
def __del__(self):
do something
私有方法,定义普通方法的时候前面加两个下划线
对象
实例化一个类之后得到的对象
封装
把一些功能的实现细节不对外暴露
第一个层面的封装(什么都不用做):创建类和对象会分别创建二者的名称空间,我们只能用类名.或者obj.的方式去访问里面的名字,这本身就是一种封装。
第二个层面的封装:类中把某些属性和方法隐藏起来(或者说定义成私有的),只在类的内部使用、外部无法访问,或者留下少量接口(函数)供外部访问。
继承
代码重用
单继承
多继承
2.7经典类(class People()),深度优先,新式类(class People(object)),广度优先
3.x广度优先
继承例子:
class Peolpe(): def __init__(self,name,age): self.name = name self.age = age def talk(self): print("%s is talking..."%self.name) def sleep(self): print("%s is sleeping..."%self.name) class Man(Peolpe): ##此处继承 pass m1 = Man("liyang",22) m1.sleep()
继承重用
class Peolpe(): def __init__(self,name,age): self.name = name self.age = age def talk(self): print("%s is talking..."%self.name) def sleep(self): print("%s is sleeping..."%self.name) class Man(Peolpe): ##此处继承 def eat(self): print("%s is eating"%self.name) def sleep(self): Peolpe.sleep(self) ##此处调用父类方法,如果没有这行,sleep方法会重写,不会执行父类方法 print("man also is sleeping") m1 = Man("liyang",22) m1.sleep()
如果子类要新增初始化参数呢,要修改一下子类
class Man(People): ##此处继承 def __init__(self,name,age,location): People.__init__(self,name,age) ##继承父类初始化参数 self.location = location ##新加一个参数
或者
class Man(People): ##此处继承 def __init__(self,name,age,location): #People.__init__(self,name,age) ##继承父类初始化参数 super(Man,self).__init__(name,age) ##使用super内置函数,新式写法 self.location = location ##新加一个参数
多继承:
# -*- coding:utf-8 -*- # Author:Brownyangyang class People(): #经典类 def __init__(self,name,age): self.name = name self.age = age def talk(self): print("%s is talking..."%self.name) def sleep(self): print("%s is sleeping..."%self.name) class Relation(object): #新式类写法,经典类没有object def make_friends(self,obj): #obj自定义对象,和谁交朋友。self是一个对象,obj也是一个对象,这么理解 print("%s is makeing friends with %s"%(self.name,obj.name)) #self.name是People那边继承过来的,obj 是定义的一个实例 #继承People()已经把name初始化了,所以继承Relation()的时候可以直接调用name,这里不需要再初始化name class Man(People,Relation): ##此处继承 def __init__(self,name,age,location): #People.__init__(self,name,age) ##继承父类初始化参数 super(Man,self).__init__(name,age) self.location = location ##新加一个参数 def eat(self): print("%s is eating"%self.name) def sleep(self): People.sleep(self) ##此处调用父类方法,如果没有这行,sleep方法会重写,不会执行父类方法 print("man also is sleeping in %s"%self.location) class Woman(People,Relation): def get_birth(self): print("%s is borning the baby"%self.name) m1 = Man("xiaoming",22,"nantong") w1 = Woman("xiaohong",32) m1.make_friends(w1)
结果:xiaoming is makeing friends with xiaohong
多态
接口重用,一种接口多次实现
方法修饰
静态方法 @staticmethod
只是名义上归类管,实际上跟类没什么关系了,实际上在静态方法里访问不了类或实例中的任何属性
类方法@classmethod
只能访问类变量,不能访问实例变量
属性方法@property
把一个方法变成一个静态属性
静态方法实例
class Dog(object): def __init__(self,name): self.name = name def eat(self,food): print("%s is eating %s"%(self.name,food)) d = Dog("liyang") d.eat("beaf")
结果:liyang is eating beaf
使用静态方法 @staticmethod 后
class Dog(object): def __init__(self,name): self.name = name @staticmethod def eat(self,food): print("%s is eating %s"%(self.name,food)) d = Dog("liyang") d.eat("beaf")
因为不能调用实例变量和类变量,上面执行会报错:
类方法实例
class Dog(object): def __init__(self,name): self.name = name def eat(self): print("%s is eating "%self.name) d = Dog("liyang") d.eat()
运行结果:liyang is eating
使用类方法@classmethod后:
class Dog(object): def __init__(self,name): self.name = name @classmethod ##只加了这个 def eat(self): print("%s is eating "%self.name) d = Dog("liyang") d.eat()
因为@classmethod 只能访问类变量,不能访问实例变量,报错如下:
如果我在类变量再定义一个那么,如下:
class Dog(object): name=“xiaoming” ##在这里新定义一个name def __init__(self,name): self.name = name @classmethod ##只加了这个 def eat(self): print("%s is eating "%self.name) d = Dog("liyang") d.eat()
结果:xiaoming is eating
说明类方法只能访问类变量,不能访问实例变量
属性方法实例:
class Dog(object): def __init__(self,name): self.name = name @property ##属性方法 def eat(self): print("%s is eating "%self.name) d = Dog("liyang") d.eat()
把一个方法变成一个静态属性,那调用方法就变了,如果不修改调用方法就会报错:
只需要 把d.eat() 改成d.eat 就可以了。
最后:
被property装饰的属性会优先于对象的属性被使用,而被propery装饰的属性,分成三种:property、被装饰
的函数名.setter、被装饰的函数名.deleter(都是以装饰器的形式)。
class people: #定义一个人的类 def __init__(self,name,sex): self.name = name self.sex = sex #p1.sex = "male",遇到property,优先用property @property #查看sex的值 def sex(self): return self.__sex #返回正真存值的地方 @sex.setter #修改sex的值 def sex(self,value): if not isinstance(value,str): #在设定值之前进行类型检查 raise TypeError("性别必须是字符串类型") #不是str类型时,主动抛出异常 self.__sex = value #类型正确的时候,直接修改__sex的值,这是值正真存放的地方 #这里sex前加"__",对sex变形,隐藏。 @sex.deleter #删除sex def sex(self): del self.__sex p1 = people("egon","male") #实例化对象p1 print(p1.sex) #查看p1的sex,此时要注意self.sex的优先级 p1.sex = "female" #修改sex的值 print(p1.sex) #查看修改后p1的sex print(p1.__dict__) #查看p1的名称空间,此时里面有sex del p1.sex #删除p1的sex print(p1.__dict__) #查看p1的名称空间,此时发现里面已经没有sex了
结果:
male
female
{
'name'
:
'egon'
,
'_people__sex'
:
'female'
}
{
'name'
:
'egon'
}