1. 类与对象
1.1 类与对象的创建
- 类名为驼峰式命名法,每个单词开头大写
- 每个类都自动继承Object类
- 类中的每个属性都必须有初始值,哪怕这个值是0或空字符串
- 可以通过“类名.属性”的方式修改类的普通属性
# 类的创建
# 由于类的方法会在下面讲述,所以这里创建的类只有属性
class Person:
name = 'Licy'
age = '18'
# 对象的创建
person1 = Person()
person2 = Person()
# 同一类的不同对象的初始属性相同
print(person1.age) #18
print(person1.name) #Licy
print(person2.age) #18
print(person2.name) #Licy
# 可修改对象的属性,但类中属性不变
person1.age = 12
print(person1.age) #12
# 可修改类的属性,对象属性都发生改变
Person.age = 100
print(person2.age) #100
1.2 类的普通方法
- 每个方法中形参self必不可少,还必须位于其他形参的前面,self代表当前对象
- 可以在类的外面,通过对象添加其独有的属性,其余对象不能调用
- 可以通过“对象名.方法名()”的方式调用类中的方法
- 普通方法不能通过“类名.方法名()的方式调用”
- 类中普通方法之间的相互调用要通过“self.方法名”的方式
class Phone:
# 创建属性
brand = "xiaomi"
price = 4999
def testSelf(self):
print(self)
def call(self):
print("正在打电话")
def color(self):
print("颜色是",self.phoneColor)
# 创建类的对象
phone1 = Phone()
phone2 = Phone()
# self代表当前对象
print(phone1) #<__main__.Phone object at 0x000001F3140072C8>
phone1.testSelf() #<__main__.Phone object at 0x000001F3140072C8>
# 调用方法
phone1.call() #正在打电话
phone2.call() #正在打电话
# phone2不能调用color方法,因为phone2没有color属性
phone1.phoneColor = 'blue'
phone1.color() #正在打电话
1.3 构造器与__ init() __方法
- __ init() __被称为类的构造器,也称为初始化方法,也属于魔术方法之一
- 当创建类的实例时,Python就会自动调用__ init() __,这一方法动态地创建属性
- __ init() __在使用参数情况下使同一类的不同对象具有不同相同属性
class Phone:
def __init__(self,brand,price):
self.brand = brand
self.price = price
def message(self):
print(self.brand,self.price)
# 创建对象
phone1 = Phone("huawei",2999)
phone2 = Phone("xiaomi",2399)
# message()方法
phone1.message() #huawei 2999
phone2.message() #xiaomi 2399
# 修改属性
phone1.brand = "xiaomi"
phone1.message() #xiaomi 2999
1.4 类方法
- 类方法通过装饰器“@classmethod”来修饰,属于类的方法,不依靠对象的存在而存在
- 类方法的参数为固定参数为cls,代表当前类,cls不能调用非类属性,因为类不能调用非类属性
- 可以通过“类名.类方法”的方式调用类方法,对象也可以调用类方法
- 类方法中不能调用普通方法,因为类方法中不能使用self
class Phone:
# 类属性
a = 123
def __init__(self,brand):
self.brand = brand
def call(self):
print("正在打电话")
@classmethod
def test(cls):
print("这是一个类方法",cls.a)
# 未创建对象,可以通过类名调用类方法
Phone.test()
# 未创建对象,可以通过类名调用类属性
print(Phone.a)
# 普通方法可以调用类方法
p1 = Phone("huawei")
p1.test()
1.5 静态方法
-
静态方法通过装饰器“@staticmethod”来修饰,无固定参数
-
静态方法与类方法及其相似,可调用的内容一致,但类方法是可通过cls和类名调用,静态方法只能用类名调用
1.6 魔术方法
魔术方法就是一个类/对象中的方法,和普通方法唯一的不同时,普通方法需要调用!而魔术方法是在特定时刻自动触发。
-
__ init __:
初始化魔术方法 触发时机:初始化对象时触发(不是实例化触发,但是和实例化在一个操作中) 参数:至少有一个self,接收对象 返回值:无 作用:初始化对象的成员 注意:使用该方式初始化的成员都是直接写入对象当中,类中无法具有其中的自创属性
-
__ new __:
实例化魔术方法 触发时机: 在实例化对时触发 参数:至少一个cls 接收当前类 返回值:必须返回一个对象实例 作用:实例化对象,开辟内存空间给__init__ 注意:实例化对象是Object类底层实现,其他类继承了Object的__new__才能够实现实例化对象。 没事别碰这个魔术方法,先触发__new__才会触发__init__
-
__ call __:
调用对象的魔术方法 触发时机:将对象当作函数调用时触发 对象() 参数:至少一个self接收对象,其余根据调用时参数决定 返回值:根据情况而定 作用:可以将复杂的步骤进行合并操作,减少调用的步骤,方便使用 注意:必须重写__call__方法才能将对象当作函数使用
-
__ del __:
析构魔术方法 触发时机:当对象没有用(没有任何变量引用该对象)的时候被触发 参数:一个self 返回值:无 作用:使用完对象是回收资源 注意:del不一定会触发当前方法,只有当前对象没有任何变量接收时才会触发
-
__ str __:
触发时机:使用print(对象名)或者str(对象名)的时候触发 参数:一个self接收对象 返回值:必须是字符串类型 作用:print(对象名)时进行操作,得到字符串,通常用于快捷操作,而不再打印出对象地址 注意:无
2. 私有化
2.1 私有化属性
在Python中,可以使用"__"添加在一变量之前,来表示对这一变量的私有化,具有以下特点:
- 私有化属性不能直接调用、修改
- 私有化属性可以通过getXxx和setXxx来调用和修改
class Student:
def __init__(self,name,age):
self.__name = name
self.__age = age
def setAge(self,age):
self.__age = age
def getAge(self):
return self.__age
s = Student("zhangsan",18)
# 不能直接调用私有属性,会报异常
# print(s.__age,s.__name)
# 可以通过getAge()方法调用Age
print(s.getAge()) #18
# 可以通过setAge()方法修改Age
s.setAge(100)
print(s.getAge()) #100
2.2 使用装饰器实现私有化
- 可以使用装饰器"@property"来修饰函数以实现私有化
- 可以使用装饰器"@同名函数名.setter"来修饰函数以实现修改属性
- 用装饰器的方式实现私有化,调用与修改属性与为私有化之前相同
class Student:
def __init__(self,name,age):
self.__name = name
self.__age = age
@property
def age(self):
return self.__age
# 同一类中不能有函数名不能相同,但使用构造器"@同名函数名.setter"可以实现同名函数
@age.setter
def age(self,age):
self.__age = age
s = Student("zhangsan",18)
# 使用装饰器@property后,可以像为私有化之前"对象.属性"的方式调用对象
print(s.age) #18
# 修改属性值,和原来未私有化之前的方式相同
s.age = 100
print(s.age) #100
3. 继承
3.1 实现继承关系
- 定义子类时,必须在括号内指定父类的名称。
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
def run(self):
print(self.name + " is running")
class Student(Person):
pass
s = Student("Peter",18)
s.run() #Peter is running
3.2 父类方法的重写
- 重写后,也可以使用super关键字调用父类的方法
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
def run(self):
print("父类的跑步方法")
class Student(Person):
def __init__(self,name,age,id):
self.name = name
self.age = age
self.id = id
def run(self):
super().run()
print("子类的跑步方法 ")
s = Student("Peter",18,12345)
s.run()
3.3 多重继承
- Python可以实现多继承
- 若多继承中父类有同名的方法,可以使用魔术方法__ mro __来检查搜索顺序
class A:
def test(self):
print("--------AAA")
class B:
def test(self):
print("--------BBB")
class C(B,A):
def func(self):
super().test()
c = C()
c.test() #--------BBB
c.func() #--------BBB
# 检查搜索顺序
print(C.__mro__) #(<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
4. 多态
4.1 多态的实现
- 在Java中多态涉及的类必须具有继承关系,而在Python中多态的实现,可以不具备继承关系,所以Python没有真正意义上的多态
class Person:
def show(self,pet): # pet即可接收Pet,也可接收Cat、Dog,也可接收Tigger
if isinstance(pet,Pet): # 判断对象(pet)是否为类(Pet)以及是否为其子类
print("{}的名字叫{}".format(pet.role,pet.nickname))
else:
print("这不能作为宠物!")
class Pet:
pass
class Cat(Pet):
role = "小猫"
def __init__(self,nickname):
self.nickname = nickname
class Dog(Pet):
role = "小狗"
def __init__(self,nickname):
self.nickname = nickname
class Tiger:
role = "老虎"
def __init__(self,nickname):
self.nickname = nickname
c = Cat("喵喵")
d = Dog("汪汪")
t = Tiger("吼吼")
p = Person()
p.show(c) #小猫的名字叫喵喵
p.show(d) #小狗的名字叫汪汪
p.show(t) #这不能作为宠物!