Python(面向对象编程)

面向对象编程(Object-Oriented Programming,简称OOP)是一种通过组织对象来设计程序的编程方法。

一.初识类和对象

1.1类-class

自然界的东西大多以类而分,物以类聚‘

1.1.1概念

定义了对象的属性和方法,比如犬类里面有个中华田园犬(对象)5岁(属性)了它会吃狗粮(方法)

1.1.2创建属于python的类

class Dog():

        pass

注意俩点:

  • 类名首字母大写
  • 小括号后有:
1.2对象-object

假如是狗类,每一个小狗就是一个对象

1.2.1概念

对象是类的实例化,具有类定义的属性与方法

小白是一只小狗,它就是狗的实例化

1.2.2创建属于python的对象

class Dog:

        pass

创建类:  dog1=Dog()   括号里可以有参数

二.属性和方法

类的属性和方法是核心部分,用于定义类的状态与行为

2.1实例属性
  • 每个实例有自己的变量,称为实例变量
  • 即每个对象创建时计算机会为其开辟单独的内存空间

属性的使用语法:实例.属性名

例:
class Dog:

    def __init__(self, name, color):  # #初始化属性,self=对象自己,传进self本身初始化属性
        self.name = name
        self.color = color
    
    
dog1=Dog("hhh","blue")
print(dog1.color,dog1.name)  #hhh,blue
  2.2实例方法
  • 实例方法就是函数,至少有一个指向实例对象的形参self(即对象本身)
  • 调用: 实例.实例方法名(调用传参)

例:
class Dog:

    def __init__(self, name, color):  # #初始化属性,self=对象自己,传进self本身初始化属性
        self.name = name
        self.color = color

    def barked(self,time):
        print(f"一只叫{self.name} {self.color}的狗一直在叫了{time}分钟")

    
dog1=Dog("hhh","blue")
dog1.barked(20)          #一只叫hhh blue的狗一直在叫了20分钟
2.3 类属性

作用:通常存储类创建的对象共有属性

注意:

  • 类是类的属性不属于类的实例(即对象)
  • 可以通过类直接访问,也可以通过类的实例(对象)访问

创建:

class Dog:

        age=5   #表示创建了一个Dog类里面的对象的age都是5

2.4类方法
  • 类方法属于类不属于类创建的对象
  • 类和类的实例都可以调用类方法
  • 类方法需要用@classmethod装饰器定义
  • 类方法至少有一个形参用于绑定类,约定为 cls
  • 类方法不能访问此类创建的对象的实例属性
#类方法
class A:
    v = 0

    @classmethod
    def set_v(cls, value):  #cls为本类
        cls.v = value
        return cls.v
    
a=A
a2=A
print(a.set_v(6))   #6
print(A.v)          #6
print(a2.v)         #6    此时调用类方法将类中属性的值改变了  即将地址中的值改变
2.5静态方法
  • 定义在类的内部,作用域为类的内部
  • 使用@staticmethod装饰器定义
  • 通过类或类的实例调用
  • 可以访问类的属性,不能访问实例属性
#静态方法
class Dog:
    color = "blue"
    @staticmethod
    def func():
        print("你好我是{cloor}")   

dog1=Dog()
dog1.func()        # 你好我是{cloor}
2.6构造方法

__new__():

负责创建对象和内存分配,在创建对象被调用时,返回一个对象实例(但通常不需要写new方法,python会自动调用基类objec的__new__():来创建对象

class Dog:
    def __new__(cls, *args, **kwargs):
        print("调用 __new__ 方法,创建对象")
        return super().__new__(cls)
2.7初始化方法

__init__():

对象被创建后来初始话对象的属性

class Dog:
        def __init__(self, value):     #self是对象本身
        print("调用 __init__ 方法,初始化对象")
        self.value = value
2.8魔术方法
  • 魔术方法,用双下滑线包裹,例如__init__等,
  • 对象通过不同操作触发相应的魔术方法
  • 很多方法由object类继承而来如 __init__,__new__
  • 可以重写自定义魔术方法

下面是一些常用的魔术方法

2.8.1用于对象与对象之间的交互

最为常见的是运算符重载

算数运算符重载

比如__add__方法

#魔术方法运算符重载
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)

    # def __str__(self):
    #     return f"Vector({self.x}, {self.y})"

v1 = Vector(1, 2)
v2 = Vector(3, 4)
v3 = v1 + v2
print(v3)           #此时打印的为v3的地址  因为打印对象时python会调用对象的__str__和__repr__方法,若没有就会输出默认字符串就是对象的内存地址
2.8.2用于对象的创建与初始化

__new__与__init__这俩个魔术方法用于对象的创建与初始化,和对象交互无关

具体可看上一小节有讲

2.8.3用于对象的字符串表示

__str__和__repr__方法用于将对象转化为字符串,方便输出调试  

#显示对象的魔术方法
class func:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def __repr__(self):
        return f"{self.width}, {self.height}"

    def __str__(self):
        return self.__repr__()

r = func(1, 2)
print(r)  # 调用 __str__ 方法    print优先调用__str__方法
print(repr(r))  # 调用 __repr__ 方法
2.8.4其他魔术方法

__len__返回对象的长度

#len
class MyList:
    def __init__(self, items):
        self.items = items

    def __len__(self):
        return len(self.items)

my_list = MyList([1, 2, 3])
print(len(my_list))  # 输出: 3

__getitem__定义对象支持索引操作(支持列表,元组那样的索引操作)

class MyList:
    def __init__(self, items):
        self.items = items

    def __getitem__(self, index):
        return self.items[index]

my_list = MyList([1, 2, 3, 4])
print(my_list[2])  # 输出: 3

__setitem__使对象支持索引赋值操作

class MyList:
    def __init__(self, items):
        self.items = items

    def __setitem__(self, index, value):
        self.items[index] = value

my_list = MyList([1, 2, 3])
my_list[1] = 10
print(my_list.items)  # 输出: [1, 10, 3]

__del__主动调用可以销毁对象,但是__del__ 方法的调用时机并不确定,因为它依赖于 Python 的垃圾回收机制

class MyClass:
    def __init__(self, name):
        self.name = name
        print(f"对象 {name} 创建")

    def __del__(self):
        print(f"对象 {self.name} 被销毁")

obj = MyClass("Test")
del obj  # 输出: 对象 Test 被销毁

 __call__使对象能像调用函数那样被调用

class Adder:
    def __call__(self, a, b):
        return a + b


# 创建 Adder 类的实例
adder = Adder()
# 像函数一样调用实例
result = adder(3, 5)
print(result)  # 输出: 8

三.oop基本特性

oop的四大基本特性是封装继承多态抽象

3.1封装
  • 是指将对象的属性和方法包装在一起,对外隐藏细节,只提供接口给外访问
  • __开头的属性或方法是私有的,在子类和类外部无法直接使用
  • 可使用内部函数访问
class Dog:
    def __init__(self, name, age):
        self.__name = name  # 私有属性
        self.age = age

    def get_name(self):
        return self.__name

    def set_name(self, name):
        self.__name = name



dog = Dog('777', 5)
print(dog.get_name())
dog.set_name('666')
3.2继承/派生
  • 儿子继承了父亲,父亲派生了儿子
  • python中所有的类最终都继承内置的obje类
3.2.1继承的实现

class dog1(dog,dog2,dog3):    (有一个基类是单继承,有多个基类是多继承)

        pass

3.2.2覆盖
  • 在子类中实现与基类同名的方法叫做覆盖
  • 实现和父类同名,但功能不同的方法
class A:
    def work(self):
        print("A.work 被调用!")

class B(A):
    '''B类继承自A类'''
    def work(self):
        print("B.work 被调用!!!")
    pass

b = B()
b.work()  # 请问调用谁?  B

a = A()
a.work()  # 请问调用谁?  A       #优先调用自己的方法
3.3多态
  • 多态是指同个方法不同对象上有不同的行为
  • 通过多态可以使不同类型的对象相同的接口表现出不同的行为
class Animal:
    def speak(self):
        print("Animal is speaking")


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


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


def animal_speak(animal):      #通常使用此方法
    animal.speak()


dog = Dog()
cat = Cat()

animal_speak(dog)  # 输出 "Woof!"
animal_speak(cat)  # 输出 "Meow!"
3.4重写

如果父类方法的功能不能满足需求,可以在子类重写父类的方法(与魔术方法类似)

class MyNumber:

    def __init__(self, value):   #初始化
        self.data = value

    def __str__(self):
        return "%s" % self.data   #自己重写


n1 = MyNumber("一只猫")
n2 = MyNumber("一只狗")
print("str(n2) ===>", str(n2))   #str(n2) ===> 一只狗
3.5super函数

super()函数是调用父类(超类)的一个方法

3.5.1基本使用
  • 子类方法中使用 super().add() 调用父类中已被覆盖的方法

class A:
     def add(self, x):
         y = x+1
         print(y)
class B(A):
    def add(self, x):
        print("子类方法")
        super().add(x)
b = B()
b.add(2)  # 3
  • 使用 super(Child, obj).myMethod() 用于子类对象调用父类已被覆盖的方法

class Parent:  # 定义父类
    def myMethod(self):
        print('调用父类方法')


class Child(Parent):        # 定义子类
    def myMethod(self):
        print('调用子类方法')


c = Child()                 # 子类实例
c.myMethod()                # 子类调用重写方法
super(Child, c).myMethod()  # 用子类对象调用父类已被覆盖的方法
3.5.2 super().__init__()     
  • 代码重用避免在子类中重复父类的初始化代码。

  • 正确初始化:确保父类的初始化逻辑即顺序

class Animal:
    def __init__(self, name):
        self.name = name
        print(f"Animal {self.name} is created.")


class Dog(Animal):
    def __init__(self, name, breed):
        # 调用父类的构造函数
        super().__init__(name)
        self.breed = breed
        print(f"Dog {self.name} of breed {self.breed} is created.")


# 创建 Dog 类的实例
dog = Dog("旺财", "中华田园犬")    
#Animal 旺财 is created.
#Dog 旺财 of breed 中华田园犬 is created.    注意顺序即可

你可能感兴趣的:(python,开发语言)