python 面向对象

本文介绍了Python中的面向对象编程基础,包括类、对象、封装、继承、多态的概念。讲解了如何定义类、属性和方法,以及类方法、实例方法的使用。还探讨了构造方法`__init__`、私有属性、公有属性、变量解析顺序(LEGB规则)和组合的概念。通过实例展示了如何在Python中实现这些特性。
摘要由CSDN通过智能技术生成

本笔记为阿里云天池龙珠计划SQL训练营的学习内容,链接为:https://tianchi.aliyun.com/specials/promotion/aicampsql

对象

类对象 --> 实例变量

三大性质 :

​ 封装

​ 继承

​ 多态

Python中的类提供了面向对象编程的所有基本功能:

类的继承机制允许多个基类,子类(派生类)可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法。

对象可以包含任意数量和类型的数据。

封装

定义

属性 + 方法

class Cat:
    color = 'red'  # 属性

    def what_color(self):  # 方法
        print(self.color)

1.对象名首字母大写

2.属性 类属性, 局部属性

​ 类属性: 1.由这个类对象创建的所有实例对象共用; 2. 在类层级定义(方法外);

​ 类属性:类外面,可以通过实例对象.类属性类名.类属性进行调用。类里面,通过self.类属性类名.类属性进行调用

​ 实例属性: 1.由实例对象单独拥有,相当于局部变量;2.在方法内定义(包括参数);

​ 实例属性 :类外面,可以通过实例对象.实例属性调用。类里面,通过self.实例属性调用。

class Cat:
    color = 'red'

    def what_color(self, ncolor):
            print(self.color)

​ color 为类属性

​ ncolor 为局部属性

​ self.color 是类属性,将在self的使用时讲到

# 创建类对象
class Test(object):
    class_attr = 100  # 类属性

    def __init__(self):
        self.sl_attr = 100  # 实例属性

    def func(self):
        print('类对象.类属性的值:',Test.class_attr)  # 调用类属性
        print('self.类属性的值',self.class_attr)     # 相当于把类属性 变成实例属性
        print('self.实例属性的值',self.sl_attr)      # 调用实例属性

# 创建a对象
a = Test()
a.func()
运行结果:
类对象.类属性的值: 100
self.类属性的值 100
self.实例属性的值 100

# 创建b对象
b = Test()
b.func()
运行结果:
类对象.类属性的值: 100
self.类属性的值 100
self.实例属性的值 100

# 通过(实例对象.类属性)修改类属性
a.class_attr = 200
# 通过(实例对象.实例属性)修改实例属性的值
a.sl_attr  = 200
a.func()
运行结果:
类对象.类属性的值: 100
self.类属性的值 200
self.实例属性的值 200

# 再次运行b对象
b.func()
运行结果:
类对象.类属性的值: 100
self.类属性的值 100
self.实例属性的值 100

# 通过(类对象.类属性)修改类属性
Test.class_attr = 300
a.func()
运行结果:
类对象.类属性的值: 300
self.类属性的值 200
self.实例属性的值 200

# 此时再执行b对象
b.func()
运行结果:
类对象.类属性的值: 300
self.类属性的值 300
self.实例属性的值 100

3.方法

类方法:在方法前面加上@classmethod 这样的方法称为类方法,类方法可以修改类属性的值。

实例方法:带有self 参数的方法

​ 1.除self参数外与普通函数相同

​ 2. self

			1.将方法定义时的第一个参数作为 self参数(self不是关键字,可写成任意参数名称,但一般约定为self)

​ 2.self是对类实例的引用

​ 3.Python 的 self 相当于 C++ 的 this 指针

class Cat:
    color = 'red'
    age = 99999

    def __init__(self, color, age):
        self.color = color  # 在实例中定义了实例参数self.color
        self.age = age

    def add_color(self):
        self.age += 1

    def what_color(self):
        print(self.color)

    def how_old(self):
        print(self.age)

cat1 = Cat('white', 1)
cat1.add_color()
cat1.how_old()
cat1.add_color()
cat1.how_old()
cat1.what_color()
#2
#3
#white
魔法,专有,双下划线方法

在 Python 中,“专有方法”(Special Methods),也称为"魔法方法"(Magic Methods)或"双下划线方法"(Double Underscore Methods)

是一组以双下划线 __ 开头和结尾的特殊方法。这些方法在类定义中具有特殊的用途,并由 Python 解释器在特定情况下自动调用。

它们被称为"专有方法"是因为它们提供了一种特殊的、针对特定操作的定制化行为,使得自定义类的对象可以在 Python 中表现得更加像内置类型。

构造方法:用于初始化对象的属性。在创建类的实例时自动调用。

__init__(self[, 变量])

继承

继承是指一个类(子类)可以继承另一个类(父类)的属性和方法。子类继承了父类的特性,这使得子类可以共享父类的功能,并且可以在此基础上添加自己特有的功能。继承提供了代码的重用机制,使得类的设计更加灵活和高效。

class 子类名(父类名):

若是父类中有相同的方法名,而在子类使用时未指定,Python 从左至右搜索,即方法在子 类中未找到时,从左到右查找父类中是否包含方法。

#类定义
class people:
    #定义基本属性
    name = ''
    age = 0
    #定义私有属性,私有属性在类外部无法直接进行访问
    __weight = 0
    #定义构造方法
    def __init__(self,n,a,w):
        self.name = n
        self.age = a
        self.__weight = w
    def speak(self):
        print("%s 说: 我 %d 岁。" %(self.name,self.age))
 
#单继承示例
class student(people):
    grade = ''
    def __init__(self,n,a,w,g):
        #调用父类的构函
        people.__init__(self,n,a,w)
        self.grade = g
    #覆写父类的方法
    def speak(self):
        print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
 
#另一个类,多继承之前的准备
class speaker():
    topic = ''
    name = ''
    def __init__(self,n,t):
        self.name = n
        self.topic = t
    def speak(self):
        print("我叫 %s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))
 
#多继承
class sample(speaker,student):
    a =''
    def __init__(self,n,a,w,g,t):
        student.__init__(self,n,a,w,g)
        speaker.__init__(self,n,t)
 
test = sample("Tim",25,80,4,"Python")
test.speak()   #方法名同,默认调用的是在括号中参数位置排前父类的方法

情况一:**子类需要自动调用父类的方法:**子类不重写__init__()方法,实例化子类后,会自动调用父类的__init__()的方法。

情况二:**子类不需要自动调用父类的方法:**子类重写__init__()方法,实例化子类后,将不会自动调用父类的__init__()的方法。

情况三:**子类重写__init__()方法又需要调用父类的方法:**使用super关键词:

多态

在Python中,多态(Polymorphism)是面向对象编程的一个重要特性,它允许使用相同的接口来处理不同类的对象,从而产生不同的行为。多态使得代码更加灵活,能够适应不同类型的对象,同时提高了代码的可复用性和可扩展性。

Python中的多态主要通过两种方式实现:

  1. 函数多态: Python是一种动态类型语言,函数的参数类型是在运行时确定的,而不是在编译时。因此,Python函数可以接受不同类型的参数,并根据参数类型的不同执行不同的操作,这就是函数多态。例如,一个函数可以接受不同类型的序列(列表、元组等),并对它们执行相同的操作。
def print_element(sequence):
    for item in sequence:
        print(item)

# 函数可以接受列表或元组,并执行相同的操作
list_data = [1, 2, 3, 4]
tuple_data = (10, 20, 30, 40)

print_element(list_data)   # Output: 1 2 3 4
print_element(tuple_data)  # Output: 10 20 30 40

  1. 方法多态: Python的类方法(包括实例方法和类方法)可以通过继承和方法重写实现多态。子类可以继承父类的方法,并根据需要对方法进行重写,从而实现自己特定的行为。当调用方法时,Python会根据对象的实际类型(子类还是父类)来选择执行哪个方法,这就是方法多态。
pythonCopy codeclass Animal:
    def make_sound(self):
        pass

class Dog(Animal):
    def make_sound(self):
        print("Woof!")

class Cat(Animal):
    def make_sound(self):
        print("Meow!")

# 调用make_sound方法时,实际执行的是对应子类的方法
dog = Dog()
cat = Cat()

dog.make_sound()  # Output: "Woof!"
cat.make_sound()  # Output: "Meow!"

在这个例子中,DogCat都继承了Animal类的make_sound方法,并对该方法进行了重写,使得每个子类都具有自己的声音。

super

super()是一个特殊的关键字或函数,用于获取父类(超类)的代理对象。通过这个代理对象,可以调用父类的方法,从而实现对父类功能的继承和扩展。

  1. 在单继承中使用super()函数: 在单继承情况下,通过super()函数可以在子类中调用父类的方法。通常,这用于在子类的方法中执行父类的逻辑,并在此基础上添加子类特有的行为。使用super()函数的形式为:super().method(),其中method是要调用的父类方法。

    示例:

    class Parent:
        def show(self):
            print("Parent")
    
    class Child(Parent):
        def show(self):
            super().show()  # 调用父类的方法
            print("Child")
    
    child = Child()
    child.show()
    
    

    输出结果:

    Parent
    Child
    
  2. 在多继承中使用super()函数: 在多继承情况下,super()函数起到协调解决方法调用顺序(Method Resolution Order,MRO)的作用。在多继承时,可能会出现菱形继承等问题,super()函数会根据类的继承顺序(通过C3线性化算法计算得出)依次调用每个父类的方法。

    示例:

    class A:
        def show(self):
            print("A")
    
    class B(A):
        def show(self):
            print("B")
            super().show()  # 调用父类A的方法
    
    class C(A):
        def show(self):
            print("C")
            super().show()  # 调用父类A的方法
    
    class D(B, C):
        def show(self):
            print("D")
            super().show()  # 调用父类B的方法
    
    d = D()
    d.show()
    

    输出结果:

    D
    B
    C
    A
    

super()函数的调用顺序是根据类的继承顺序(Method Resolution Order,MRO)确定的,可以通过class_name.__mro__属性查看类的方法解析顺序。在继承链中,super()函数按照该顺序依次调用各个父类的方法,以达到协调多继承的目的。

需要注意的是,super()函数不仅可以用于调用父类的方法,

还可以用于调用父类的构造方法,从而实现子类构造方法对父类构造方法的继承。

class a:
    def __init__(self):
        print('a')


class b(a):
    def __init__(self):
        super().__init__()
        print('b')

b1 = b()

#a
#b

公有和私有

在 Python 中定义私有变量只需要在变量名或函数名前加上“__”两个下划线,那么这个函数变量就会为私有的了。

  1. 公有(Public)
    • 公有属性和方法可以在类的内部和类的外部访问。
    • 在类定义中不使用任何修饰符(即默认情况下),声明的属性和方法都是公有的。
    • 公有属性和方法在类的内部通过 self 访问,在类的外部通过对象名访问。
class MyClass:
    def __init__(self):
        self.public_var = 123   # 公有属性

    def public_method(self):
        return "This is a public method."

obj = MyClass()
print(obj.public_var)        # Output: 123
print(obj.public_method())   # Output: This is a public method.
  1. 私有(Private)
    • 私有属性和方法只能在类的内部访问,对于类的外部是不可见的。
    • 使用双下划线 __ 开头的属性和方法被认为是私有的,它们不能通过对象名直接访问。
    • 可以在类内部通过 self 访问私有属性和方法。
class MyClass:
    def __init__(self):
        self.__private_var = 456   # 私有属性

    def __private_method(self):
        return "This is a private method."

    def public_method(self):
        return self.__private_method()

obj = MyClass()
# 无法直接访问私有属性和方法
# print(obj.__private_var)       # Error
# print(obj.__private_method())  # Error

# 可以通过公有方法间接访问私有方法
print(obj.public_method())      # Output: This is a private method.

需要注意的是,虽然使用双下划线 __ 开头的属性和方法被认为是私有的,但在 Python 中实际上它们只是进行了名称改写,即在名称前添加了 _类名,以避免命名冲突。因此,仍然可以通过 _类名__私有属性_类名__私有方法 的形式来访问私有属性和方法,但不推荐这样做,因为这违背了类的封装性原则,使得私有属性和方法不再具有隐藏和保护的效果。(伪私有

变量解析顺序

在Python 中,当不同范围内有多个同名变量(例如局部变量、实例属性、类属性)时,Python 会按照特定的顺序来解析变量名称。这个顺序被称为“LEGB”规则,其中每个字母代表搜索顺序的一个范围:

  1. 本地(L):Python首先在本地范围内搜索变量,本地范围指的是定义该变量的当前函数或方法。如果在此范围内找到该变量,Python 将使用它并停止搜索。
def example_function():
    x = 10   # Local variable
    print(x) # Accessible only inside the function

example_function()  # Output: 10
  1. 封闭 (E):如果在局部作用域中找不到该变量,Python 将在直接封闭函数的作用域中进行搜索(如果当前作用域嵌套在另一个函数内)。它继续搜索多个封闭范围,直到找到变量或到达全局范围。
def outer_function():
    y = 20   # Enclosing variable

    def inner_function():
        print(y)  # Accesses the enclosing variable y

    inner_function()

outer_function()  # Output: 20
  1. 全局 (G):如果在任何封闭作用域中都找不到该变量,Python 将在全局作用域中查找它。全局作用域是指模块级作用域,其中存储模块顶层定义的变量。
global_var = 30   # Global variable

def my_function():
    print(global_var)  # Accessing the global variable

my_function()  # Output: 30
  1. 内置 (B):如果在本地、封闭或全局作用域中找不到该变量,Python 最终会在内置作用域中搜索它,该作用域包含所有 Python 内置函数和类型。
print(len([1, 2, 3]))  # 'len' is a built-in function

此 LEGB 规则确保 Python 以可预测的顺序搜索变量,并避免变量解析中的歧义。如果同名变量存在于多个作用域中,Python 将根据 LEGB 规则使用第一个匹配作用域中找到的变量。

绑定

Python 严格要求方法需要有实例才能被调用,这种限制其实就是 Python 所谓的绑定概念。

在 Python 中,绑定(Binding)是将名称(变量名)与对象(值)关联起来的过程。当你创建一个变量并将值赋给它时,就会发生绑定。绑定意味着在内存中创建了一个对象,并将该对象与变量名关联起来,使得你可以通过变量名来引用和操作这个对象。

Python 中的绑定分为两种类型:

  1. 名称绑定(Name Binding)

    • 在 Python 中,给一个变量名赋值就是创建一个名称绑定。这意味着将变量名与特定的对象(值)关联起来。
    • 变量名在赋值之前必须先被声明或引用。一旦绑定完成,变量名可以在之后的代码中使用。

    示例:

    x = 42  # 将整数值 42 绑定到变量名 x
    y = "Hello"  # 将字符串 "Hello" 绑定到变量名 y
    
    # 使用已绑定的变量名
    print(x)  # Output: 42
    print(y)  # Output: Hello
    
  2. 对象绑定(Object Binding)

    • 对象绑定是指将一个对象与变量名关联起来,使得该变量名成为该对象的引用。在 Python 中,所有变量都是对对象的引用。
    • 多个变量名可以指向同一个对象,因此一个对象可以有多个对象绑定。

    示例:

    a = [1, 2, 3]  # 将列表对象 [1, 2, 3] 绑定到变量名 a
    b = a  # 将变量名 b 绑定到和 a 相同的对象
    
    # 修改 a 所引用的对象,同时 b 也会受影响
    a.append(4)
    print(b)  # Output: [1, 2, 3, 4]
    

在 Python 中,绑定是动态的,变量可以在任何时候指向不同的对象。例如,你可以在运行时更改变量名的绑定对象:

pythonCopy codex = 42
print(x)  # Output: 42

x = "Hello"
print(x)  # Output: Hello

在这个例子中,变量 x 在不同的时刻绑定了整数 42 和字符串 “Hello”,表现出了 Python 的动态特性。这也是 Python 灵活和易于使用的一个特点。

组合

在面向对象编程中,组合(Composition)是一种将多个类组合在一起以创建更复杂的对象的关系。组合是一种强关联关系,其中一个类(称为容器类)包含另一个类(称为成员类)的对象作为其属性。通过组合,容器类可以使用成员类的功能,从而实现了代码的复用和模块化。

组合和继承是面向对象编程的两种常见的关联方式,它们有不同的特点和适用场景。

在组合中,一个类将另一个类的对象作为属性

而在继承中,一个类继承另一个类的属性和方法

例子第14行

class Engine:
    def __init__(self, horsepower):
        self.horsepower = horsepower

    def start(self):
        print("Engine started.")

    def stop(self):
        print("Engine stopped.")

class Car:
    def __init__(self, year, horsepower):
        self.year = year
        self.engine = Engine(horsepower)  # 使用组合,将Engine类的对象作为Car类的属性

    def start(self):
        print(f"{self.year} is starting.")
        self.engine.start()

    def stop(self):
        print(f"{self.year} is stopping.")
        self.engine.stop()

# 创建Car类的对象
car1 = Car(2022, 150)
car2 = Car(2023, 180)

# 调用Car类的方法
car1.start()
car1.stop()

car2.start()
car2.stop()
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值