Python 关于面向对象

面向对象具有三大特征

(一)、封装

有些时候我们不希望把对象的属性公开,就可以把它设为私有,python并没有像其他语言对成员的权限控制系统,如private和protected,默认情况下,python的所有属性都是公有的,可以被访问到,要设成私有,则在前面加双下划线

在Python语言中,所谓的私有,不过是一种假象。当我们在类中定义私有成员时,在程序内部会将其处理成_类名 + 原有成员名称的形式。也就是会将私有成员的名字进行一下伪装而已,如果我们使用处理之后的名字,还是能够进行访问的.程序:私有的伪装

  • xx: 公有变量
  • _x: 保护变量,只能在类的内部和类的子类,实例中使用
  • __xx: 私有变量,双前置下划线,避免与子类中的属性命名冲突,无法在外部直接访 问(名字重整所以访问不到)
  • __xx__: 双前后下划线,用户名字空间的魔法对象或属性。例如:__init__ , __ 不要自己发明这样的名字(通过name mangling(名字重整(目的就是以防子类意外重写基类的方法或者 属性)如:_Class__object)机制就可以访问private了)
  • xx_: 单后置下划线,用于避免与Python关键词的冲突
class Person:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    def get_name(self):
        return self.__name

    def get_age(self):
        return self.__age


p = Person('Tom', 22)
# print(p.__name) # 报AttributeError异常
print(p.get_name())  # Tom
print(p.get_age())  # 22

# _Class__object任然可以获取属性
print(p._Person__name)  # Tom
(二)、继承

继承可以使子类拥有父类的属性和方法,并且可以重写这些方法,加强代码的复用性,python中子类可以有多个父类,但是不建议这样使用,一般会产生重复调用的问题,Super().方法名,可以调用父类的方法(不用传参,作用是调用父类的方法,传的是子类实例的值)

class Animal:
    def eat(self):
        print('Animal eat')

    def run(self):
        print('Animal run')


class Dog(Animal):
    def dog_call(self):
        print('dog_call')


class Cat(Animal):
    def cat_call(self):
        print('cat_call')


d = Dog()
d.dog_call()  # dog_call
d.eat()  # Animal eat
(三)、多态

指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式

因为Python是鸭子类型,因此,多态在Python中体现的不明显

class Animal:
    def eat(self):
        print('Animal eat')

    def run(self):
        print('Animal run')


class Dog(Animal):
    def call(self):
        print('Dog call')


class Cat(Animal):
    def call(self):
        print('Cat call')


def call(obj):
    obj.call()


c = Cat()
d = Dog()
call(c)  # Cat call
call(d)  # Dog call

类成员

描述:
  • 属性
    • 普通属性
    • 静态属性
  • 方法
    • 普通方法
    • 类方法
    • 静态方法
  • property属性
代码演示:
class Simple:
    # 静态字段
    static_field = '这是一个静态字段'

    def __init__(self, normal_field):
        # 普通字段
        self.normal_field = normal_field

    # 普通方法
    def method(self):
        print('这是一个普通方法')

    # 类方法
    @classmethod
    def class_method(cls):
        print('这是一个类方法')

    # 静态方法
    @staticmethod
    def static_method():
        print('这是一个静态方法')

    # 定义属性:获取数据
    @property
    def prop(self):
        return self.__value

    # 设置数据
    @prop.setter
    def prop(self, value):
        self.__value = value

    # 删除数据
    @prop.deleter
    def prop(self):
        del self.__value


s = Simple('这是一个普通字段')
print(s.normal_field)
print(s.static_field)
s.method()
Simple.class_method()
Simple.static_method()

输出信息

这是一个普通字段
这是一个静态字段
这是一个普通方法
这是一个类方法
这是一个静态方法
  • 普通属性属于对象
  • 静态属性属于类
  • 普通方法:由对象调用,有self参数,调用方式时,将调用方法的对象赋值给self
  • 类方法:由类调用,有cls参数,调用方法事件,将调用方法的类赋值给cls
  • 静态方法:由类调用,无默认参数
  • property属性:在普通方法上添加@property装饰器,setter装饰器赋值,getter装饰器取值

内置方法

描述:
类的内建属性和方法 说明 触发方式
init 构造初始化函数 创建实例后,赋值时使用,在new
new 生成实例所需属性 创建实例时
class 实例所在的类 实例.class
str 实例字符串表示,可读性 print(类实例),如没实现,使用repr结果
repr 实例字符串表示,准确性 类实例 回车 或者 print(repr(类实例))
del 析构 del删除实例
dict 实例自定义属性 vars(实例.dict)
doc 类文档,子类不继承 help(类或实例)
getattribute 属性访问拦截器 访问实例属性时
bases 类的所有父类构成元素 类名.bases

说明:

__getattr__:当一般位置找不到attribute的时候,会调用getattr,(有返回值)返回一个值或AttributeError异常.
__getattribute__:无条件被调用,通过实例访问属性.

代码演示:
class Person:
    # 构造方法
    def __new__(cls, *args, **kwargs):
        print('__new__')
        return super().__new__(cls)  # 如果没有调用父类的构造函数,初始化函数是不会被调用的

    # 初始化方法
    def __init__(self, name, age):
        print('__init__')
        self.name = name
        self.age = age

    # 对象输出
    def __str__(self):
        return '我的名字%s,年龄%d' % (self.name, self.age)

    # 对象当函数调用时执行
    def __call__(self, *args, **kwargs):
        print('__call__')
        return self.name

    # 释放对象时执行
    def __del__(self):
        print('__del__')


p = Person('Tom', 22)
print(p)
print(p())

输出信息

__new__
__init__
我的名字Tom,年龄22
__call__
Tom
__del__
__getattr__和__getattribute__关系

当访问某个实例属性时, getattribute会被无条件调用,如未实现自己的getattr方法,会抛出AttributeError提示找不到这个属性,如果自定义了自己getattr方法的话,方法会在这种找不到属性的情况下被调用 。

一般重写__getattr__方法

class Person:
    def __init__(self):
        self.name = 'Jim'

    def __getattribute__(self, item):
        print('item:%s' % item)
        if item == 'name':
            return '调用getattribute'
        else:
            return object.__getattribute__(self, item)

    def __getattr__(self, item):
        print('__getattr__')
        return 'default'

测试一:

p = Person()
print(p.name)

输出信息:
item:name
调用getattribute

测试二:

p = Person()
print(p.name2)

输出信息:
item:name2
__getattr__
default
__getattribute__的坑
class Person:
    def __getattribute__(self, item):
        print('__getattribute__')
        if item.startswith('a'):
            return 'hahaha'
        else:
            return self.test # 这里会陷入递归调用

p = Person()
print(p.b)

猜你喜欢

转载自blog.csdn.net/qq_14876133/article/details/81135005