Python是一门面向对象的语言,所以在Python中需要创建类和对象
1. 面向对象
1.1 类的创建
类的定义:
class [类名]:
[语法块]
class EmptyClass:
pass
1.2 类的使用
class EmptyClass:
pass
empty = EmptyClass()
print(type(empty)) # <class '__main__.EmptyClass'>
1.3 类的构造方法
在Python中,构造方法就是类的 __init__ 方法,类在实例化时会自动调用 __init__ 方法,用于创建类的实例
class Dog:
def __init__(self):
print("汪汪汪!")
dog = Dog() # 汪汪汪!
1.4 类的属性
class Dog:
def __init__(self, name):
self.name = name
self.age = 3
dog = Dog("旺财")
print(dog.name) # 旺财
print(dog.age) # 3
注意:属性必须使用 “self” 加上点的方式赋值,不能直接定义变量。直接定义的变量生命周期只在函数内,函数执行完变量就会被销毁。
class Dog:
def __init__(self, name):
self.name = name
age = 3
dog = Dog("旺财")
print(dog.name) # 旺财
# Dog 没有age这个属性,出现错误: AttributeError: 'Dog' object has no attribute 'age'
print(dog.age)
1.5 类的方法
class Dog:
def __init__(self, name):
self.name = name
def play(self):
print("汪汪汪!我是", self.name)
dog = Dog("旺财")
dog.play() # 汪汪汪!我是 旺财
1.6 私有属性
为了防止实例随意修改属性,需要用到私有属性。私有属性使用 “__” 作为开头
class Dog:
def __init__(self, name):
self.__name = name
def play(self):
print("汪汪汪!我是", self.__name)
dog = Dog("旺财")
dog.play() # 汪汪汪!我是 旺财
# 私有属性对外不可见,出现错误: AttributeError: 'Dog' object has no attribute '__name'
print(dog.__name)
提供 set 方法修改私有属性
class Dog:
def __init__(self, name):
self.__name = name
self.__age = None
print(self.__name, "生成成功")
def set_age(self, age):
if not isinstance(age, int):
print("输入的年龄必须是数字!")
return False
if age <= 0:
print("输入的年龄必须大于0!")
return False
self.__age = age
def play(self):
print("汪汪汪!我今年", self.__age, "岁")
dog = Dog("旺财") # 旺财 生成成功
dog.set_age("hello") # 输入的年龄必须是数字!
dog.set_age(-20) # 输入的年龄必须大于0!
dog.set_age(3)
dog.play() # 汪汪汪!我今年 3 岁
1.7 私有方法
私有方法只能在内部被调用,实例不能直接调用
class Dog:
def __say(self, name):
print(name)
def play(self):
self.__say("汪汪汪")
dog = Dog()
dog.play() # 汪汪汪
# 私有方法不能被实例调用,出现错误: AttributeError: 'Dog' object has no attribute '__say'
dog.__say()
2. 继承和多态
面向对象有三大特性: 封装、继承、多态
2.1 继承
注意: Python 支持多重继承,一个类可以有多个父类。
子类的定义如下:
class SubClass(BaseClass1, BaseClass2):
[语法块]
class Animal:
def __init__(self, name):
self.name = name
def play(self):
print("我是", self.name)
# 继承
class Dog(Animal):
pass
dog = Dog("旺财")
dog.play() # 我是 旺财
继承有两点需要注意:
- 在继承中,如果子类定义了构造方法,则父类的构造方法 __init__ 不会被自动调用,需要在子类中手动调用。
class Animal:
def __init__(self, name):
self.name = name
def play(self):
print("我是", self.name)
class Dog(Animal):
def __init__(self):
print("旺财")
# 父类的构造方法没有被执行,
# 出现错误: TypeError: __init__() missing 1 required positional argument: 'name'
dog = Dog() # AttributeError: 'Dog' object has no attribute 'name'
dog.play()
正确方式
class Animal:
def __init__(self, name):
self.name = name
def play(self):
print("我是", self.name)
class Dog(Animal):
def __init__(self):
super(Dog, self).__init__("旺财")
dog = Dog()
dog.play() # 我是 旺财
- 子类不能继承父类中的私有方法,也不能调用父类的私有方法。
class Animal:
def __init__(self, name):
self.__name = name
def __play(self):
print("Animal, __play")
def play(self):
print("Animal, play")
class Dog(Animal):
def __init__(self):
super().__init__("旺财")
def say(self):
self.play()
self.__play()
dog = Dog()
dog.say()
# Animal, play
# AttributeError: 'Dog' object has no attribute '_Dog__play'
2.2 多态
继承可以帮助我们重复使用代码,但是有时候子类的行为不一定完全和父类一样
2.2.1 子类使用父类实现
class Animal:
def say(self):
print("Animal")
class Dog(Animal):
pass
class Cat(Animal):
pass
dog = Dog()
dog.say() # Animal
cat = Cat()
cat.say() # Animal
2.2.2 子类自定义方法实现
当子类和父类存在相同的方法时,子类的方法会覆盖父类的方法,这样代码在运行时总是会调用子类的方法
class Animal:
def say(self):
print("Animal")
class Dog(Animal):
def say(self):
print("Dog")
class Cat(Animal):
def say(self):
print("Cat")
dog = Dog()
dog.say() # Dog
cat = Cat()
cat.say() # Cat
2.2.3 判断类的实例
使用内置函数 isinstance
print('--------------------------------------- 2.3 ---------------------------------------')
print(isinstance(dog, Dog)) # True
print(isinstance(dog, Animal)) # True
print(isinstance(cat, Cat)) # True
print(isinstance(cat, Animal)) # True
2.2.4 接收子对象的方法
class Animal:
def say(self):
print("Animal")
class Dog(Animal):
def say(self):
print("Dog")
class Cat(Animal):
def say(self):
print("Cat")
def animal_say(animal: Animal):
animal.say()
dog = Dog()
cat = Cat()
animal_say(dog) # Dog
animal_say(cat) # Cat
2.3 鸭子类型
在程序设计中,鸭子类型(Ducking Type) 是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口决定的,而是由当前方法和属性的集合决定的
class Dog:
def say(self):
print("Dog")
class Cat:
def say(self):
print("Cat")
def animal_say(animal):
animal.say()
dog = Dog()
cat = Cat()
animal_say(dog) # Dog
animal_say(cat) # Cat
3. 类变量和实例变量
3.1 类变量
类变量:不需要实例化就能直接使用,相当于绑定在类上
class Animal:
name = "动物"
print(Animal.name) # 动物
3.2 实例调用类变量
class Animal:
name = "动物"
dog = Animal()
cat = Animal()
print(dog.name) # 动物
print(cat.name) # 动物
Animal.name = "哺乳类动物"
print(dog.name) # 哺乳类动物
print(cat.name) # 哺乳类动物
4. 静态方法和类方法
4.1 静态方法
静态方法: 使用 “@staticmethod” 进行装饰。不需要默认参数 “self”,不能调用成员变量和成员方法。和类变量一样,可以直接使用
class Animal:
name = "动物"
@staticmethod
def play():
print("playing")
Animal.play() # playing
4.2 类方法
类方法: 使用 “@classmethod” 进行装饰。需要一个初始参数cls指向类本身,可以读取和修改类变量
class Animal:
name = "动物"
@classmethod
def play(cls):
print(cls.name, "playing")
Animal.play() # 动物 playing