文章目录
1 类的成员
成员变量:数据成员,保存数据。例如学号,姓名;
构造方法:初始化成员变量;
成员方法:类中定义的函数;
属性:对类封装的特殊方法。
实例变量和实例方法属于对象,通过对象调用;类变量和类方法属于类,通过类调用。对象也被称为实例,创建对象就是类的实例化。
1.1 实例变量
实例变量:某个对象个体特有的数据,例如狗狗的名字和年龄
# coding=utf-8
class Dog:
def __init__(self,name,age):
self.name = name #创建和初始化实例变量name
self.age = age #创建和初始化实例变量age
d = Dog("球球", 2)
print('我家狗叫{0},今年{1}岁了。'.format(d.name, d.age ) )
D:\anaconda\python.exe
我家狗叫球球,今年2岁了。
Process finished with exit code 0
对实例变量通过“对象.实例变量”形式访问;
类中的"self"表示当前对象,构造方法中的"self"参数说明这个方法属于实例,self.age中self表示age属于实例,即实例成员变量。
1.2 构造方法
" _init_(self)",创建和初始化实例变量,第一个参数应该是self,之后的参数用来初始化实例变量。调用构造方法时不需要传入self参数。
# coding=utf-8
class Dog:
def __init__(self,name,age,sex="雌性"):
self.name = name
self.age = age
self.sex = sex
d = Dog("球球", 2)
d1 = Dog("哈哈", 1, '雄性')
d2 = Dog(name="旺旺", sex="雄性", age=2)
print('我家狗叫{0},今年{1}岁了,是{2}。'.format(d.name, d.age, d.sex))
print('我家狗叫{0},今年{1}岁了,是{2}。'.format(d1.name, d.age, d1.sex))
print('我家狗叫{0},今年{1}岁了,是{2}。'.format(d2.name, d2.age, d2.sex ))
D:\anaconda\python.exe
我家狗叫球球,今年2岁了,是雌性。
我家狗叫哈哈,今年2岁了,是雄性。
我家狗叫旺旺,今年2岁了,是雄性。
Process finished with exit code 0
1.3 实例方法
实例方法是某个实例(对象)个体特有的方法。
定义实例方法时,第一个参数也是self,这会将当前实例与该方法绑定起来,说明该方法属于实例。在调用方法时不需要传入self。
在调用时采用"对象.实例方法"形式
# coding=utf-8
class Dog:
def __init__(self,name,age,sex="雌性"):
self.name = name
self.age = age
self.sex = sex
#实例方法
def run(self):
print("{}在跑……".format(self.name))
def eat(self,food):
print("{}在吃{}".format(self.name, food))
d = Dog("球球", 2)
d.run()
d.eat("骨头")
D:\anaconda\python.exe
球球在跑……
球球在吃骨头
Process finished with exit code 0
1.4 类变量
由所有实例共享的变量。例如银行账户类,有三个成员变量:amount(账户金额),rate(利率),owner(账户ID)。其中的amount,owner对每个账户都不同,rate对每个账户都相同,因此amount,owner是实例变量,rate是类变量。
类变量通过“类名.类变量”调用。
# coding=utf-8
class Account:
rate = 0.0432
def __init__(self,owner,amount):
self.owner = owner
self.amount = amount
a = Account("Tony", 1000000.0)
print("{}在银行存了{},利率为{}".format(a.owner, a.amount, Account.rate ) )
D:\anaconda\python.exe
Tony在银行存了1000000.0,利率为0.0432
Process finished with exit code 0
1.5 类方法
类方法属于类不属于个体实例。在定义类方法时,第一个参数不是self,而是类本身(cls)。需要使用@装饰器修饰函数、方法和类,起到约束作用。
通过“类名.类方法”调用
# coding=utf-8
class Account:
rate = 0.0432
def __init__(self,owner,amount):
self.owner = owner
self.amount = amount
@classmethod
def rate_by(cls,amt): #cls代表类自身
return cls.rate*amt #此处cls可用类名替换
# return Account.rate*amt 也可以
rate1 = Account.rate_by(12000.0)
print("计算利息{0:.4f}".format(rate1))
D:\anaconda\python.exe
计算利息518.4000
Process finished with exit code 0
注意:类方法可以访问类变量和其它类方法,不能访问实例变量和实例方法
2 封装性
2.1 私有变量和私有方法
私有变量和私有方法只允许类的内部调用,外部只能通过方法调用私有变量,类的外部不可以访问私有方法。
2.1.1 类的外部调用私有方法:
# coding=utf-8
#类的外部不能调用私有方法
class Account:
rate = 0.0432
def __init__(self,owner,amount):
self.owner = owner
self.__amount = amount #私有变量
def __desc1(self):
print("私有方法:{}在银行存了{}元".format(self.owner, self.__amount))
def desc(self):
print("实例方法:{}在银行存了{}元".format(self.owner,self.__amount))
a = Account("123",123456)
a.__desc1() #外部调用私有方法
D:\anaconda\python.exe
Traceback (most recent call last):
File "D:/pythonProject/python学习/Filter.py", line 15, in <module>
a.__desc1()
AttributeError: 'Account' object has no attribute '__desc1'
Process finished with exit code 1
2.1.2 类的内部调用私有方法:
# coding=utf-8
class Account:
rate = 0.0432
def __init__(self,owner,amount):
self.owner = owner
self.__amount = amount #私有变量
def __desc1(self):
print("私有方法:{}在银行存了{}元".format(self.owner, self.__amount))
def desc(self):
print("实例方法:{}在银行存了{}元".format(self.owner,self.__amount))
def interuse(self): #内部调用私有方法
print("内部调用私有方法:")
self.__desc1()
a = Account("123",123456)
a.interuse()
D:\anaconda\python.exe D:/pythonProject/python学习/Filter.py
内部调用私有方法:
私有方法:123在银行存了123456元
Process finished with exit code 0
2.1.3 类的外部调用私有变量:
# coding=utf-8
class Account:
rate = 0.0432
def __init__(self,owner,amount):
self.owner = owner #实例变量
self.__amount = amount #私有变量
def __desc1(self):
print("私有方法:{}在银行存了{}元".format(self.owner, self.__amount))
def desc(self):
print("实例方法:{}在银行存了{}元".format(self.owner,self.__amount))
a = Account("123",123456)
print(a.owner) #外部调用实例变量
print(a.__amout) #外部调用私有变量
D:\anaconda\python.exe
Traceback (most recent call last):
File "D:/pythonProject/python学习/Filter.py", line 16, in <module>
print(a.__amout)
AttributeError: 'Account' object has no attribute '__amout'
123
Process finished with exit code 1
2.1.4 类的内部调用私有变量:
# coding=utf-8
class Account:
rate = 0.0432
def __init__(self,owner,amount):
self.owner = owner
self.__amount = amount #私有变量
def desc(self): #类的内部调用私有变量
print("实例方法:{}在银行存了{}元".format(self.owner,self.__amount))
a = Account("123",123456)
a.desc()
D:\anaconda\python.exe
实例方法:123在银行存了123456元
Process finished with exit code 0
2.2 使用属性
为了实现对象的封装,在一个类中不应该有公有的成员变量,这些成员变量应该被设计为私有的,然后通过公有的set和get方法访问。
# coding=utf-8
class Account:
rate = 0.0432
def __init__(self,owner,amount):
self.owner = owner
self.__amount = amount #私有变量
def desc(self):
print("实例方法:{}在银行存了{}元".format(self.owner,self.__amount))
def get_amount(self):
return self.__amount
def set_aomunt(self,amount):
self.__amount = amount
a = Account("123",123456)
print("修改前账户金额:{}".format(a.get_amount()))
a.set_aomunt(789442)
print("修改后账户金额:{}".format(a.get_amount()))
D:\anaconda\python.exe
修改前账户金额:123456
修改后账户金额:789442
Process finished with exit code 0
使用set和get比较麻烦,可以在类中定义属性来替代get()和set()
# coding=utf-8
class Account:
rate = 0.0432
def __init__(self,owner,amount):
self.owner = owner
self.__amount = amount #私有变量
def desc(self):
print("实例方法:{}在银行存了{}元".format(self.owner,self.__amount))
# 在方法前加入修饰器使得方法成为属性,使用的时候类似公有变量
@property
def amount(self): #替代 get_amount(self),该处方法名就是去掉下划线之后的变量名
return self.__amount
@amount.setter
def aomunt(self,amount): #替代 set_age(self,amount)
self.__amount = amount
a = Account("123",123456)
print("修改前账户金额:{}".format(a.amount))
a.aomunt = 789442
print("修改后账户金额:{}".format(a.amount))
D:\anaconda\python.exe
修改前账户金额:123456
修改后账户金额:789442
Process finished with exit code 0
3 继承性
子类继承父类时,只继承父类的公有的成员变量和方法。构造方法在初始化类的实例成员变量时,也初始化父类的实例成员变量。
3.1 单继承
# coding=utf-8
class Account:
rate = 0.0432
def __init__(self,owner,amount):
self.owner = owner
self.__amount = amount #私有变量
def show_owner(self):
print("{}在银行存了{}元".format(self.owner, self.__amount))
def change(self):
self.__amount = 20589
print("金额变动到{}元".format(self.__amount))
class Savings(Account): #储蓄账户继承父类账户
def __init__(self,owner,amount=963258):
super().__init__(owner,amount)
class Credit(Account): #信用账户继承父类账户
def __init__(self,owner,amount=963258):
super().__init__(owner,amount)
a = Savings("123")
c = Savings("321")
b = Credit("456")
a.show_owner()
a.change()
a.show_owner()
c.show_owner()
b.show_owner()
结果说明某个子类的某个实例在改变父类中的变量值时仅仅改变了自己实例中的值,其他类继承的同一个父类变量值没有被改变,同一个类的其它实例继承的同一个父类变量值也没有被改变:
D:\anaconda\python.exe D:/pythonProject/python学习/Filter.py
123在银行存了963258元
金额变动到20589元
123在银行存了20589元
321在银行存了963258元
456在银行存了963258元
Process finished with exit code 0
3.2 多继承
当子类继承多个父类时,如果多个子类中有相同的成员方法或者成员变量,则优先继承左边的父类,从左到右依次继承。
# coding=utf-8
class Horse:
def __init__(self,name):
self.name = name
def show_info(self):
print("马儿的名字是{}".format(self.name))
def run(self):
print("马儿在奔跑~")
class Donkey:
def __init__(self,name):
self.name = name
def show_info(self):
print("驴儿的名字是{}".format(self.name))
def run(self):
print("驴儿在奔跑~")
def eat(self):
print("驴儿在吃草~")
class Mule(Horse, Donkey):
def __init__(self, name):
super().__init__(name)
m = Mule("莉莉")
m.run()
m.eat()
m.show_info()
D:\anaconda\python.exe
马儿在奔跑~
驴儿在吃草~
马儿的名字是莉莉
Process finished with exit code 0
3.3 方法重写
3.2多继承中,Mule类中的show_info()方法继承自Horse父类,显示的信息是“马儿的名字是莉莉”,而莉莉是马儿和小驴的孩子,应该是小骡儿,因此在Mule类中重写show_info方法,实现正确的显示。方法重写是当子类中的方法名与父类相同时,会重写父类方法。
# coding=utf-8
class Horse:
def __init__(self,name):
self.name = name
def show_info(self):
print("马儿的名字是{}".format(self.name))
def run(self):
print("马儿在奔跑~")
class Donkey:
def __init__(self,name):
self.name = name
def show_info(self):
print("驴儿的名字是{}".format(self.name))
def run(self):
print("驴儿在奔跑~")
def eat(self):
print("驴儿在吃草~")
class Mule(Horse, Donkey):
def __init__(self, name):
super().__init__(name)
def show_info(self):
print("骡儿的名字是{}".format(self.name))
m = Mule("莉莉")
m.run()
m.eat()
m.show_info()
D:\anaconda\python.exe
马儿在奔跑~
驴儿在吃草~
骡儿的名字是莉莉
Process finished with exit code 0
4 多态性
4.1 继承与多态
多态指对象可以表现出多种形态。例如,猫,狗,鸭子都属于动物,他们都会叫,但叫的方式不同。在多个子类继承父类,并重写父类方法后,这些子类所创建的对象之间就是多态的,这些对象采用采用不同的方式实现父类方法。
# coding=utf-8
class Animal:
def speak(self):
print("动物会说话~")
class Dog(Animal):
def speak(self):
print("小狗说话汪汪汪~")
class Cat(Animal):
def speak(self):
print("小猫说话喵喵喵~")
dog = Dog()
cat = Cat()
dog.speak()
cat.speak()
D:\anaconda\python.exe
小狗说话汪汪汪~
小猫说话喵喵喵~
Process finished with exit code 0
4.1 鸭子类型测试与多态
鸭子类型测试:若看到一只鸟走起来像鸭子,游泳起来像鸭子,叫起来也像鸭子,那这只鸟可以被叫做鸭子。
python解释器不检查发生多态的对象是否继承自相同的父类,只要他们有相同的方法,他们之间就是多态的。
设计一个函数start(),接收具有speak()方法的对象。
# coding=utf-8
def start(obj):
obj.speak()
class Animal:
def speak(self):
print("动物会说话~")
class Dog(Animal):
def speak(self):
print("小狗说话汪汪汪~")
class Cat(Animal):
def speak(self):
print("小猫说话喵喵喵~")
class Car:
def speak(self):
print("小汽车说话嘀嘀嘀~")
start(Dog())
start(Cat())
start(Car())
D:\anaconda\python.exe
小狗说话汪汪汪~
小猫说话喵喵喵~
小汽车说话嘀嘀嘀~
Process finished with exit code 0