面向对象的三大属性

一..封装

指将数据(属性)和操作数据的方法(行为)捆绑为一个独立的单元(即类或对象),并隐藏内部实现细节。

私有化

单下划线:非公开API

有一个前缀下划线的变量或方法应被视为非公开的API,例如_var1,这种不具备强制力

双下划线:名称改写

有两个前缀下划线,并至多一个后缀下划线的标识符。例如__x,会被改写为_类名__x。只有在类内部可以通过__x访问,其他地方无法访问或只能通过_类名__x访问。

 私有属性

class Person:
    def __init__(self,name,age,height)
        self.name = name
        #当前属性不想暴露,这种私有化不具备强制性
        self._age = age
        self.__height = height
        

p1 = Person("zs",24,188)
print(p1._age) #是可以访问的
print(p1.__height) #无法访问
print(p1._Person__height) #此时才可以访问

私有方法

通过双下划线定义私有方法

class Person:
    #定义私有方法
    def __private_method(self):
        print("private")

    #通过实例方法,调用私有方法
    def do_something(self):
        self.__private_method()

p = Person()
p.do_something() #输出:private
p._Person__private_method() #输出:private

property

通过公开方法调用和修改私有属性

class Person:
    def __init__(self,name,age):
        self.name = name
        self.__age = age

    #通过公开方法调用和修改私有属性,java的处理方式
    def set_age(self,age):
        self.__age = age

    def get_age(self):
        return self.__age


p1 = Person("zs",28)
print(p1.get_age())

可以通过@property装饰器将一个方法转化为属性来调用。转化后直接使用. 方法名 来使用,而无需使用 .方法名()

class Circle:
    def __init__(self, radius):
        self._radius = radius

    @property
    def radius(self):
        return self._radius

# 使用
circle = Circle(5)
print(circle.radius)  # 输出: 5
 
class Person:
    def __init__(self,name,age):
        self.name = name
        self.__age = age

    @property    
    def age(self):
        return self.__age



p1 = Person("zs",25)
print(p1.age)

读写属性

将方法名设置为去掉双下划线的私有属性名,使用 属性名.setter 装饰

class Person:
    def __init__(self,name,age):
        self.name = name
        self.__age = age

    @property    
    def age(self):
        return self.__age

    @age.setter
    def age11(self,age):
        self.__age = age

p = person("zs",25)
p.age11 = 18
print("p.age")

property的注意事项

setter前面的名必须和property的方法和私有属性去掉双下划线一致

二.继承

子类继承父类中的属性和方法,实现代码重用。子类可以新增自己特有的方法,也可以重写父类的方法。

子类不能继承父类的私有属性和私有方法,因为存在名称改写,但是可以通过改写后的名称直接访问父类的私有成员。

单继承

语法: class 子类名(父类)

注意:子类要输入父类的__init__的赋值

class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        return "Animal sound"

class Dog(Animal):
    def speak(self):
        return "Bark"

# 创建实例
dog = Dog("Buddy")
print(dog.name)    # 输出: Buddy
print(dog.speak()) # 输出: Bark
 

多继承

class Person:
    home = "earth"
    def __init__(self,name):
        self.name = name

    def eat(self):
        print("eating")

class Student(Person):
    def __init__(self,name,subject,grade):
        self.subject = subject
        self.grade = grade

    def sub(self):
        print(self.subject)

    def study(self):
        print("study...")

class Yellowperson(Person):
    color = "yellow"

class Chinesestudent(Student,Yellowperson):
    country = "china"


liujie = Chinesestudent("liujie","math",9,)
liujie.eat()
liujie.sub()

复用父类方法

子类可以在类中使用super().方法名()或者 父类名.方法名() 来调用父类的方法

class Parent:
    def greet(self):
        print("Hello from Parent")

class Child(Parent):
    def greet(self):
        super().greet()  # 调用父类的 greet 方法 或者Parent.great(self)
        print("Hello from Child")
 

方法解析顺序

可以使用类名.__mro__访问类的继承链来查看方法解析顺序

class Person:
    home = "earth"
    def __init__(self,name):
        self.name = name

    def eat(self):
        print("eating")

class Student(Person):
    def __init__(self,name,subject,grade):
        self.subject = subject
        self.grade = grade

    def sub(self):
        print(self.subject)

    def study(self):
        print("study...")

class Yellowperson(Person):
    color = "yellow"

class Chinesestudent(Student,Yellowperson):
    country = "china"



Chinesestudent.__mro__
"""输出:(__main__.Chinesestudent,
 __main__.Student,
 __main__.Yellowperson,
 __main__.Person,
 object)
"""

super()调用的方法和mro一样

最好写成

super(A,self).__init__(a,b,c)

super(B,self).__init__(a,b,c)

方法的重写

在子类中定义与父类方法重名的方法,调用时会调用子类中重写的方法

class Animal:
    def make_sound(self):
        print("Generic animal sound")

class Dog(Animal):
    #重写父类方法
    def make_sound(self):
        print("Bark")

class Cat(Animal):
    #重写父类方法
    def make_sound(self):
        print("Meow")

# 创建对象并调用方法
dog = Dog()
cat = Cat()
dog.make_sound() #Bark
cat.make_sound() #Meow
 

    重写注意:

    • Python不支持传统的方法重载(同名方法不同参数),后定义的方法会覆盖前一个。要么名字相同,参数不同。
    • 在子类中可以定义和父类同名的方法,调用的时候会执行子类中重写的方法。对父类的方法重新实现功能

    三.多态

    基于继承的多态

    子类可以重写父类的方法,实现不同的行为。调用时根据对象的实际类型决定执行哪个方法。

    class Animal:
        def speak(self):
            pass
    
    class Dog(Animal):
        def speak(self):
            return "Woof!"
    
    class Cat(Animal):
        def speak(self):
            return "Meow!"
    
    def animal_sound(animal):
        print(animal.speak())
    
    dog = Dog()
    cat = Cat()
    animal_sound(dog)  # 输出: Woof!
    animal_sound(cat)  # 输出: Meow!
     
    

    鸭子类型(Duck Typing)

    Python 不强制要求对象继承特定类,只要对象具有所需的方法或属性即可。

    class Car:
        def drive(self):
            return "Vroom!"
    
    class Bicycle:
        def drive(self):
            return "Pedal!"
    
    def vehicle_action(vehicle):
        print(vehicle.drive())
    
    car = Car()
    bike = Bicycle()
    vehicle_action(car)   # 输出: Vroom!
    vehicle_action(bike)  # 输出: Pedal!
     
    

    更多推荐