类的语法:
class Animal(object): #class是创建类的关键字 Animal是类名 object是新式类的写法 def __init__(self,name): #初始化方法,也称构造方法,创建了类的实例时会调用该方法, self代表实例本身,谁调用类,self就是谁。name是属性,也成实例变量 self.name = name def talk(self): #self在定义类的方法时必须有,虽然调用时不必传入参数 print('animal [%s] is talking'%self.name) a1 = Animal('dog') #类的实例化 ,python会自动把a1变量赋值给self这个参数 a1.talk()
#1,实例化时会在内存里开辟一块空间指向 a1这个变量名
#2,调用Animal类并执行__init__(...)为了把name等属性跟刚开辟的a1关联起来,关联后就可以直接用a1.name 调用了
#3,所以这个__init__(…)方法里的,self.name = name,self.role = role的意思就是要把这几个值存到a1的内存空间里
类的实例化:把一个抽象的类通过实例化变为一个具体的对象
面向对象编程三个特点:封装,继承,多态
封装:把使用构造方法将内容封装到某个具体对象中,然后通过对象直接或者self间接获取被封装内容。
继承:在OOP程序设计中,定义一个class的时候,可以从某个现有的class继承,通过继承创建的新的class 称为 子类 或 派生类 ,被继承的class称为 基类、父类 或 超类。
例如:
class Animal(object): def talk(self): print('animal is talking') class Dog(Animal): #子类 pass class Cat(Animal): #子类 pass d=Dog() c=Cat() d.talk() #继承了父类的方法 c.talk() #继承了父类的方法 得到 animal is talking animal is talking
继承的时候,如果父类和子类都有相同方法,执行哪一个呢?
class Animal(object): def __init__(self): self.func() def func(self): print("Animal Class") class Dog(Animal): def func(self): #与父类同名的方法func() print("Dog class") d = Dog() #实例化了子类 结果: Dog class
对象之间的交互:
''' 对象之间的交互 ''' class Animal: '''奥特曼和小怪兽都有的属性,名字,伤害值,生命值''' def __init__(self,name,damage,life_value): self.name = name self.damage = damage self.life_val = life_value class People(Animal): '''人可以攻击小怪兽''' def attack(self,monster): monster.life_val -= self.damage class Monster(Animal): '''小怪兽咬人''' def bite(self,people): people.life_val -= self.damage p=People('奥特曼',30,2000) m=Monster('小怪兽',20,1000) print("奥特曼初始生命值",p.life_val) m.bite(p) m.bite(p) print("奥特曼被咬了两口:",p.life_val) print('--------------------------------') print("小怪兽初始生命值",m.life_val) p.attack(m) print("小怪兽挨揍了之后生命值",m.life_val) 结果: 奥特曼初始生命值 2000 奥特曼被咬了两口: 1960 -------------------------------- 小怪兽初始生命值 1000 小怪兽挨揍了之后生命值 970
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Monster: def __init__(self,name,damage,life_value): self.name = name self.damage = damage self.life_value = life_value def bite(self,person): '''怪兽咬人,人的生命值减少''' person.life_value -= self.damage class People: def __init__(self,name,money,life_value,damage = 0): '''人的属性:名字,生命值,钱,战斗力为0''' self.damage = damage self.name = name self.life_value = life_value self.money = money class Weapon: '''武器类:名字,价格,战斗力''' def __init__(self,name,value,damage): self.name = name self.value = value self.damage = damage def buyed_by(self,people): #击中对方,对方生命值减少 people.money -= self.value people.damage += self.damage def shooted(self,obj): #击中对方,对方生命值,战斗力减少 obj.life_value -= self.damage obj.damage -= 100 if __name__ == "__main__": p = People('正义者',1000,5,0) m = Monster('怪兽',100,5) w = Weapon('AK48',200,500) if p.money > w.value: print("正义者买了一把枪") w.buyed_by(p) p.weapon = w else: print("正义者还买不起武器,只能等死了...") print("怪兽生命值:%s,战斗力:%s"%(m.life_value,m.damage)) p.weapon.shooted(m) print("正义者开枪了") print("怪兽生命值:%s,战斗力:%s" % (m.life_value, m.damage)) 结果: 正义者买了一把枪 怪兽生命值:5,战斗力:100 正义者开枪了 怪兽生命值:-495,战斗力:0
继承和重写
class SchoolMember(object): #父类 def __init__(self,name,age): self.name = name self.age = age class Student(SchoolMember): #子类 def __init__(self,name,age,grade): #先重写 super(Student,self).__init__(name,age) #后继承 super关键字 self.grade = grade def prt_name(self): print("student [%s]'s grade is [%s]"%(self.name,self.grade)) class Teacher(SchoolMember): #子类 def __init__(self,name,age,course): #重写 super(Teacher,self).__init__(name,age) #继承 self.course = course def Teach(self): print('Teacher %s is teaching [%s] now'%(self.name,self.course)) s=Student('lily',22,14) #类的实例化 s.prt_name() #调用方法 t=Teacher('alex',30,'python') #类的实例化 t.Teach()
可以通过 issubclass(sub,super) 判断是否是继承关系
print(issubclass(Student,SchoolMember))
多态:实现接口的重用。
class Animal(object): def __init__(self,name): self.name = name def talk(self): print('animal [%s] is talking'%self.name) class Dog(Animal): def talk(self): #父类里已存在talk方法。子类可以进行方法重写 print('Dog [%s] is wow wow wow'%self.name) class Cat(Animal): def talk(self): print('Cat [%s] is miao miao miao'%self.name) def func(obj): #一个接口 多种形态 obj.talk() d=Dog('小黑') c=Cat('小喵') func(d) #调用子类Dog的方法 func(c) #调用子类Cat的方法 ----------> Dog [小黑] is wow wow wow Cat [小喵] is miao miao miao
类变量vs实例变量
类变量是创建类时就存在类的内存空间里面的。而实例变量是类实例化时,存在实例的内存空间里的
class People(object): num = 0 #类变量 def __init__(self,name): self.name = name #实例变量,通过实例来访问 def study(self): People.num += 10 # 类变量使用类来访问 print('num[%s] student %s is studing...'%(self.num,self.name)) p = People('lily') p.study() print(People.num) print(p.num) -----------> num[10] student lily is studing... 10 10 #------------错误的示例--------------------- class People(object): num = 0 #类变量 def __init__(self,name): #实例变量 self.name = name def study(self): self.num += 10 #不能改变类变量,而是跟类变量重名的实例变量 print('num[%s] student %s is studing...'%(self.num,self.name)) p = People('lily') p.study() print(People.num) print(p.num) -----------------------> num[10] student lily is studing... 0 10
静态方法
@staticmethod装饰器可以把一个方法变成静态方法。 静态方法不能访问实例变量和类变量,跟类没什么关联,只能通过类名来调用方法
class People(object): num = 0 #类变量 def __init__(self,name): self.name = name #实例变量 @staticmethod def study(self): print('student %s is studing...'%(self.name)) #不能访问self.num 也不能访问self.name p = People('lily') p.study() -------------------> 报错:study() missing 1 required positional argument: 'self'
除非把实例本身当做传给study方法 p.study(p)
类方法
@classmethod 装饰器可以把一个方法变成类方法。类方法只能访问类变量不能访问实例变量
class People(object): num = 0 #类变量 def __init__(self,name): self.name = name #实例变量 @classmethod def study(self): print('num[%s] student %s is studing...'%(self.num,self.name)) #可以访问self.num 类变量,不能访问self.name实例变量 p = People('lily') p.study() -------------> 报错AttributeError: type object 'People' has no attribute 'name'
属性方法
@property 把一个方法变成属性
class People(object): def __init__(self,name): self.name = name @property # 把study方法变成一个属性 def study(self): print('student %s is studying...'%self.name) p = People('lily') p.study # 属性,只读 p.name = 'jack' #此时外部可以调用name变量,这时可以使用__把name变成私有变量,使外部无法调用 p.study ---------------> student lily is studying... student jack is studying... p.study = 'hena' #修改的话会报错,因为study属性不可修改 ---------------> AttributeError: can't set attribute
可以加上一个setter改为可写属性
class People(object): def __init__(self): self.__name = None @property # 把study方法变成一个属性 def study(self): return self.__name @study.setter # 把study属性变成一个可写的属性 def study(self,value): self.__name = value @study.deleter #删除 def study(self): del self.__name p = People() print(p.study) p.study = 'lily' print(p.study) -----------------> None lily del p.study print(p.study) ----------------------> #报错,说明p.study属性已经被删除 AttributeError: 'People' object has no attribute '_People__name'
类的特殊成员方法
__str__ 和 __repr__
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#不加__str__时 >>> class P: ... def __init__(self,name,age): ... self.name = name ... self.age = age >>> a=P('lily',999) >>> print(a) <__main__.P object at 0x7f4703aac400> #如果要把一个类的实例变成str,就需要用__str__ >>> class P: ... def __init__(self,name,age): ... self.name = name ... self.age = age ... def __str__(self): ... return 'name: %s,age: %s'%(self.name,self.age) ... >>> b=P('xiaohei',10) >>> b <__main__.P object at 0x7f4703aac748> >>> print(b) name: xiaohei,age: 10 #__str__()用于显示给用户看,而__repr__()是显示给开发人员看 >>> class P: ... def __init__(self,name,age): ... self.name = name ... self.age = age ... def __str__(self): ... return 'name: %s,age: %s'%(self.name,self.age) ... __repr__ = __str__ ... >>> c=P('lin',20) >>> c name: lin,age: 20 >>> print(c) name: lin,age: 20
__doc__ 类的描述信息
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: ''' this is a test class ''' def func(self): pass print(A.__doc__) --------------------------> this is a test class
__module__ 对象在哪个模块
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# python example.py class A: def func(self): pass a = A() print(a.__module__) #结果-------------------> __main__ # python test.py from example import A x = A() print(x.__module__) #结果------------------> example example
__class__ 对象是什么类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# python example.py class A: def func(self): pass a = A() print(a.__class__) -----------------> <class '__main__.A'> # python test.py from example import A x = A() print(x.__class__) --------------------> <class 'example.A'> <class 'example.A'>
__dict__ 查看类或对象中的成员
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self,name): self.name = name def func(self): return self.name print("类的成员:",A.__dict__) a = A('lily') print("对象的成员:" ,a.__dict__) -----------------> 类的成员: {'__module__': '__main__', '__init__': <function A.__init__ at 0x0000004135DFDD08>, 'func': <function A.func at 0x0000004135DFDE18>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None} 对象的成员: {'name': 'lily'}
python的反射机制
getattr(object,name,[value]) 获取
setattr(object, name, value) 设置
hasattr(object, name) 判断
delattr(object, name) 删除
>>> class Myclass(object): ... def __init__(self,name): ... self.name = name ... def func(self,value): ... self.value = value ... print("value is: ",self.value) ... >>> obj = Myclass("lily") >>> hasattr(obj,"name") #判断obj对象是否有name属性 True >>> hasattr(Myclass,"name") #判断类是否有name属性 False >>> hasattr(Myclass,"func") #判断class是否有func方法 True >>> hasattr(obj,"func") True >>> getattr(obj,"name") #获取值 'lily' >>> getattr(obj,"func") #获取obj.func方法的内存地址 <bound method Myclass.func of <__main__.Myclass object at 0x7f78283302e8>> >>> x=getattr(obj,"func") >>> x(22) # 调用方法 等同于obj.func(22) value is: 22 >>> >>> def test_run(server): ... print("%s running..."%server) ... >>> setattr(obj,"run",test_run) #将test_run绑定到obj对象,命名为run >>> obj.run("ftp") ftp running...
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import sys class Webserver(object): def __init__(self,host): self.host = host def start(self): print("server is start...") def stop(self): print("server is stop...") def restart(self): self.start() self.stop() def test_run(self,name): print("%s running...%s"%(name,self.host)) if __name__ == '__main__': s = Webserver('localhost') if hasattr(s,sys.argv[1]): #判断是否有这个方法 func = getattr(s,sys.argv[1]) #获取s.start方法的内存地址 func() setattr(s,"run",test_run) s.run(s,'mysql') delattr(Webserver,'stop') #只能类删除类方法,实例删不了,实例只能删除实例属性host s.restart() #会报错'Webserver' object has no attribute 'stop'