opp

本文深入解析面向对象编程(OOP)的核心概念,包括面向对象的分析(OOA)、设计(OOD)、实现(OOI)和编程(OOP),并详细介绍了Python中如何使用下划线和双下划线进行成员变量的封装,探讨了继承、多继承、抽象类的使用,以及魔术方法、类方法、静态方法和属性(property)的高级应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

OO:面向对象
- OOA:面向对象的分析
- OOD:面向对象的设计
- OOI:xxx的实现
- OOP:xxx的编程面向对象的实现过程
- OOA->OOD->OOI:

#dict前后各有两个下划线
对象所有成员检查
A.__dict__
class A():
    name = "xiaoxiong"
    age = 18
print(A._dict_)=>{'__module__': '__main__', 'name': 'dana', 'age': 18, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
B=A()
print(B._dict_)=>{}  
print(B.name)=>xiaoxiong  

使用类访问绑定类的方法时, 如果类方法中需要访问当前类的成员,可以通过 __class__成员名来访问

class Teacher():
    name = "dana"
    age = 19
    
    def say(self):
        self.name = "yaona"
        self.age = 17
        print("My name is {0}".format(self.name))
        # 调用类的成员变量需要用 __class__
        print("My age is {0}".format(__class__.age))
    def sayAgain():
        print(__class__.name)
        print(__class__.age )
        print("Hello, nice to see you again")
        
t = Teacher()
t.say()=>My name is yaona  My age is 19
# 调用绑定类函数使用类名
t.sayAgain()=>报错
Teacher.sayAgain()=>dana  19  Hello, nice to see you again

[python中下划线使用]

_xxx:表示内部使用,不能被from M imoprt *导入
xxx_:表示避免和关键字冲突,如Tkinter.Toplevel(master, class_='ClassName')
__xxx:更彻底的private.用到了name mangling技术,会自动加上类名前缀.不能被子类和类外访问.
__xxx__:魔术方法或用户控制的命名空间.

私有

私有成员是最高级别的封装,只能在当前类或对象中访问
在成员前面添加两个两个下划线即可
Python的私有不是真私有,是一种成为name mangling的改名策略

__age = 18

受保护的封装 protected

- 受保护的封装是将对象成员进行一定级别的封装,然后,在类中或者子类中都
可以进行访问,但是在外部不可以
- 封装方法: 在成员名称前添加一个下划线即可
_age = 18

继承

子类和父类定义同一个名称变量,则优先使用子类本身
扩充父类函数

class Person():
    name="NoName"
    def work(self):
        print("make some money")
#父类写在括号内
class Teacher(Person):
    name="xiaoxiong"
    def work(self):
        # 扩充父类的功能只需要调用父类相应的函数,首先名字相同
        # 扩充父类的两种方法,第一种是通过父类名调用
        # 第二种super代表得到父类
        Person.work(self)//super().work()//super(Teacher.self).work()
        self.make_test()
t=Teacher()
#子类和父类定义同一个名称变量,则优先使用子类本身
print(t.name)=>xiaoxiong    
t.work()

构造函数

__init__就是构造函数
每次实例化的时候,第一个被自动的调用

class Dog():
    def __init__(self):
        print("I am init in dog")
xiaoming=Dog()=>i am init in dog

继承中的构造函数

class Animel():
    def __init__(self):
        print("Animel")
class PaxingAni(Animel):
    def __init__(self):
        print(" Paxing Dongwu")
class Dog(PaxingAni):
    def __init__(self):
        print("I am init in dog")     
# 实例话的时候,自动调用了Dog的构造函数
# 因为找到了构造函数,则不在查找父类的构造函数
kaka = Dog()=>I am init in dog
# 猫没有写构造函数
class Cat(PaxingAni):
    pass
# 此时应该自动调用构造函数,因为Cat没有构造函数,所以查找父类构造函数
# 在PaxingAni中查找到了构造函数,则停止向上查找
c = Cat()=>Paxing Dongwu

多继承
子类可以直接拥有父类的属性和方法,私有属性和方法除外

class Bird():
    def __init__(self, name):
        self.name = name
    def fly(self):
        print("I am flying.....")
class SuperMan(Person, Bird, Fish):
    def __init__(self, name):
        self.name = name
s=SuperMan("xiaoxiong")
s.fly()=>i am flying        

issubclass()

判断参数 class 是否是类型参数 classinfo 的子类。
所有参数都是object的子类

class A():
    pass
class B(A):
    pass
class C():
    pass
print( issubclass(B, A))=>True
print( issubclass(C, A))=>False
print( issubclass(B, object))=>True

isinstance()

检测一个对象是否是一个类的实例

class A():
    pass
a = A()
print(isinstance(a, A))=>True
print(isinstance(A, A))=>Flase
  • hasattr:检测一个对象是否有成员xxx
class A():
    name="xiaoxiong"
    pass
a = A()
print(hasattr(a, "name"))=>True
  • getattr: get attribute
  • setattr: set attribute
  • delattr: delete attribute
  • dir: 获取对象的成员列表

类的常用魔术方法

  • 魔术方法就是不需要人为调用的方法,基本是在特定的时刻自动触发
  • 魔术方法的统一的特征,方法名被前后各两个下滑线包裹
  • 操作类
    • __init__: 构造函数
    • __new__: 对象实例化方法,此函数较特殊,一般不需要使用
    • __call__: 对象当函数使用的时候触发
    • __str__: 当对象被当做字符串使用的时候调用
    • __repr__: 返回字符串,跟__str__具体区别请百度
  • 描述符相关
    • __set__
    • __get__
    • __delete__
  • 属性操作相关
    • __getattr__: 访问一个不存在的属性时触发
    • __setattr__: 对成员属性进行设置的时候触发
      • 参数:
        • self用来获取当前对象
        • 被设置的属性名称,以字符串形式出现
        • 需要对属性名称设置的值
      • 作用:进行属性设置的时候进行验证或者修改
      • 注意: 在该方法中不能对属性直接进行赋值操作,否则死循环
      • 参看案例
  • 运算分类相关魔术方法
    • __gt__: 进行大于判断的时候触发的函数
      • 参数:
        • self
        • 第二个参数是第二个对象
        • 返回值可以是任意值,推荐返回布尔值
        • 案例
class A():
    name = "xiaoxiong"
    age = 18
    #必须初始化name
    def __init__(self, name=0 ):
        print("哈哈,我被调用了")
        
    def __call__(self):
        print("我被调用了again")
       
    def __str__(self):
        return "这是个例子"
   
    def __getattr__(self, name):
        print("没找到呀没找到")
        print(name)

    def __setattr__(self, name, value):
        print("设置属性: {0}".format(name))
        # 下面语句会导致问题,死循环
        # self.name = value
        # 此种情况,为了避免死循环,规定统一调用父类魔法函数
        super().__setattr__(name, value)
    


a = A()=>哈哈,我被调用了
a()=>我被调用了again
print(a)=>这是个例子
print(a.name)=>xiaoxiong
#输出None的原因是没有return语句,默认return None
print(a.addr)  =>没找到呀没找到  addr  None
print(a.__dict__)=>{}
a.age=18 =>设置属性:age
print(a.__dict__)=>{'age':18}

class Student():
    def __init__(self, name=0):
        self.name = name
     
    def __gt__(self, obj):
        print("哈哈, {0} 会比 {1} 大吗?".format(self.name, obj.name))
        return self.name > obj.name

stu1 = Student("one")
stu2 = Student("two")
print(stu1 > stu2)=>哈哈, one 会比 two 大吗?  False

类和对象的三种方法

实例方法
- 需要实例化对象才能使用的方法,使用过程中可能需要截止对象的其他对象的方法完成
静态方法
- 不需要实例化,通过类直接访问
类方法
- 不需要实例化

# 三种方法的案例
class Person:
    # 实例方法
    def eat(self):
        print(self)
        print("Eating.....")
    
    #类方法
    # 类方法的第一个参数,一般命名为cls,区别于self
    @classmethod
    def play(cls):
        print(cls)
        print("Playing.....")
        
    # 静态方法
    # 不需要用第一个参数表示自身或者类
    @staticmethod
    def say():
    
        print("Saying....")
        
yueyue = Person()

# 实例方法
yueyue.eat()=><__main__.Person object at 0x0000021678FDB240> Eating.....
# 类方法
Person.play()=><class '__main__.Person'> Playing.....
yueyue.play()=><class '__main__.Person'> Playing.....
#静态方法
Person.say()=>Sayying.......
yueyue.say()=>Sayying.......

属性的三种用法
1, 赋值
2. 读取
3. 删除 del

类属性 property

class A():
    def __init__(self):
        self.name = "haha"
        self.age =18
    # 此功能,是对类变量进行读取操作的时候应该执行的函数功能
    def get(self):
        print("我被读取了")
        return self.name
    # 模拟的是对变量进行写操作的时候执行的功能
    def fset(self, name):
        print("我被写入了,但是还可以做好多事情")
        self.name = "王子:" + name 
        
    # fdel模拟的是删除变量的时候进行的操作
    def f2del(self):
        pass
        
    # property的四个参数顺序是固定的
    # 第一个参数代表读取的时候需要调用的函数
    # 第二个参数代表写入的时候需要调用的函数
    # 第三个是删除
    name2 = property(get, fset, f2del, "这是一个property的例子")
    
a = A()
print(a.name)=>haha
a.name2="xiaoxiong"=>我被写入了,但是还可以做好多事情
print(a.name2)=>我被读取了 王子:xiaoxiong
del a.name2
print(a.name2)=>我被读取了 王子:xiaoxiong

抽象类

抽象方法: 没有具体实现内容的方法成为抽象方法

  • 抽象方法的主要意义是规范了子类的行为和接口
  • 抽象类的使用需要借助abc模块
    抽象类:包含抽象方法的类叫抽象类,通常成为ABC类
    抽象类可以包含抽象方法,也可以包含具体方法
    • 抽象类中可以有方法也可以有属性
    • 抽象类不允许直接实例化
    • 必须继承才可以使用,且继承的子类必须实现所有继承来的抽象方法
    • 假定子类没有是现实所有继承的抽象方法,则子类也不能实例化
    • 抽象类的主要作用是设定类的标准,以便于开发的时候具有统一的规范
import abc

#声明一个类并且指定当前类的元类
class Human(metaclass=abc.ABCMeta):

    # 定义一个抽象的方法
    @abc.abstractmethod
    def smoking(self):
        pass
    
    # 定义类抽象方法
    @abc.abstractclassmethod
    def drink():
        pass
    
    # 定义静态抽象方法
    @abc.abstractstaticmethod
    def play():
        pass
    
    def sleep(self):
        print("Sleeping.......")

组装一个类
类其实是一个类定义和各种方法的自由组合

  • 可以定义类和函数,然后自己通过类直接赋值
  • 可以借助于MethodType实现
  • 借助于type实现
  • 利用元类实现- MetaClass
    • 元类是类
    • 备用来创造别的类
from types import MethodType

class A():
    pass

def say(self):
    print("Saying... ...")
    
a = A()
a.say = MethodType(say, A)
a.say()=>say......

利用type造一个类
先定义类应该具有的成员函数

def say(self):
    print("Saying.....")
    
def talk(self):
    print("Talking .....")
    
#用type来创建一个类
A = type("AName", (object, ), {"class_say":say, "class_talk":talk})

# 然后可以像正常访问一样使用类
a = A()

a.class_say()=>Say......
a.class_talk()=>Talk......
# 元类演示

# 元类写法是固定的,必须继承自type
# 元类一般命名以MetaClass结尾
class TulingMetaClass(type):
    # 注意以下写法
    def __new__(cls, name, bases, attrs):
        #自己的业务处理
        print("哈哈,我是元类呀")
        attrs['id'] = '000000'
        attrs['addr'] = "北京海淀区公主坟西翠路12号"
        return type.__new__(cls, name, bases, attrs)
    
# 元类定义完就可以使用,使用注意写法
class Teacher(object, metaclass=TulingMetaClass):
    pass

t = Teacher()=>哈哈,我是元类呀

t.id
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值