zoukankan      html  css  js  c++  java
  • python基础 day26 面向对象-super方法、封装、property装饰器、反射

    一、super 方法

    class A:
        def func(self):
            print('A')
    class B(A):
        def func(self):
            super().func()
            print('B')
    class C(A):
        def func(self):
            super().func()
            print('C')
    class D(B,C):
        def func(self):
            super().func()
            print('D')
    print(D.mro())
    # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
    D().func()
    '''
    A
    C
    B
    D
    '''
    
    • super 是按照mro顺序来寻找当前类的下一个类的
    • 在python3中不需要传参数,自动就帮我们寻找当前类的mro顺序的下一个类中的同名方法
    • 在python2中的新式类中,需要我们主动传递参数super(子类的名字, 子类的对象).函数名(),这样才能够帮我们调用到这个子类的mro顺序的下一个类中的方法。
    • 在python2的经典类中,并不支持使用super来找下一个类。

    即上面代码在D类中找super的func,可以写super().func(),也可写成super(D, self).func(),但是在python2中必须写成super(D, self).func()

    在单继承的程序中,super就是找父类。

    class User:
        def __init__(self, name):
            self.name = name
    
    class VIPUser(User):
        def __init__(self, name, level, start_time, end_time):
            super().__init__(name)
            self.level = level
            self.start_time = start_time
            self.end_time = end_time
    
    jason = VIPUser('jason', 10, '05-03', '06-03')
    print(jason.__dict__)
    # {'name': 'jason', 'level': 10, 'start_time': '05-03', 'end_time': '06-03'}
    

    二、封装

    封装:把属性和方法装起来

    广义:把属性和方法装起来,外部不能直接调用,要通过类的名字调用

    狭义:把属性和方法藏起来,外部不能调用,只能在内部偷偷调用

    • 给一个名字前面加上双下划线的时候,这个名字就变成了一个私有的
      所有的私有的内容或名字都不能在类的外部直接调用,只能在类的内部使用
    class User:
        def __init__(self, username, password):
            self.usr = username
            self.__pwd = password  # 私有的实例变量/私有的对象属性
    
    jason = User('jason', '123456')
    print(jason.usr)  # jason
    print(jason.__pwd)  # 此时会报错
    
    • 如果想要查看或者修改私有的实例变量只能在类中定义函数来查看
    class User:
        def __init__(self, username, password):
            self.usr = username
            self.__pwd = password  # 私有的实例变量/私有的对象属性
        def get_pwd(self):
            return self.__pwd
        def change_pwd(self):
            old_pwd = input('enter old password:')
            if old_pwd == self.__pwd:
                new_pwd1 = input('enter new password:')
                new_pwd2 = input('enter new password again:')
                if new_pwd1 == new_pwd2:
                    self.__pwd = new_pwd2
    jason = User('jason', '123456')
    print(jason.usr)  # jason
    print(jason.get_pwd())  # 123456
    jason.change_pwd()
    print(jason.get_pwd())
    

    同理,也可以有私有的静态变量

    class Map:
        country = 'china'
        __language = 'chinese'
        def get(self):
            return Map.__language
    
    a = Map()
    print(a.country)  # china
    print(a.__language)  # 报错
    print(a.get())  # chinese
    

    同理,也可以有私有的方法

    import hashlib
    class User:
        def __init__(self,name,password):
            self.usr = name
            self.__pwd = password  # 私有的实例变量
        def __md5_pwd(self):  # 私有的方法
            ret = hashlib.md5()
            ret.update(self.__pwd.encode('utf-8'))
            return ret.hexdigest()
        def get_pwd(self):
            return self.__md5_pwd()
    
    jason = User('jason', 'abcd')
    print(jason.get_pwd())
    

    所有的私有化都是为了让用户不在外部调用类中的某个名字
    如果完成私有化,那么这个类的封装度就更高了,封装度越高各种属性和方法的安全性也越高 ,但是代码越复杂

    私有的内容能不能被子类使用? 不能

    class Foo:
        def __init__(self):
            self.func()
        def func(self):
            print("in Foo")
    class Son(Foo):
        def func(self):
            print("in Son")
    
    Son()  # in Son
    
    class Foo:
        def __init__(self):
            self.__func()
        def __func(self):
            print("in Foo")
    class Son(Foo):
        def __func(self):
            print("in Son")
    
    Son()  # in Foo
    
    class Foo:
        def __func(self):
            print("in Foo")
    class Son(Foo):
        def __init__(self):
            self.__func()
    Son()  # 报错
    

    三、类中的装饰器

    • property

    property 应用场景一:把一个方法伪装成属性,在调用这个方法时不需要加()就可以直接得到返回值

    import time
    class Person:
        def __init__(self, name, birth):
            self.name = name
            self.birth = birth
        @property
        def age(self):  # 装饰的这个方法,不能有参数
            return time.localtime().tm_year - self.birth
    
    jason = Person('jason', 1996)
    print(jason.age)
    

    property 应用场景二:和私有属性合作

    class User:
        def __init__(self,username,password):
            self.usr = username
            self.__pwd = password
        @property
        def pwd(self):
            return self.__pwd
    
    jason = User('jason', 1234)
    print(jason.pwd)
    

    property 进阶

    class Goods:
        discount = 0.8
        def __init__(self,name,origin_price):
            self.name = name
            self.__price = origin_price
        @property
        def price(self):
            return self.__price * self.discount
        @price.setter
        def price(self,new_value):
            if isinstance(new_value,int):
                self.__price = new_value
    
    apple = Goods('apple', 10)
    print(apple.price)  # 调用的是被@property装饰的price
    apple.price = 20  # 调用的是被setter装饰的price
    print(apple.price)
    

    三、反射

    反射使用场景
    1.反射对象的实例变量
    2.反射类的静态变量/绑定方法/其他方法
    3.模块中的所有变量:导入的模块/当前.py文件

    语法

    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
        def func(self):
            print('aloha')
    
    j = Person('jason', 24)
    d = Person('dog', 5)
    ret = getattr(j, 'name')
    print(ret)
    ret = getattr(d, 'func')
    ret()
    

    使用反射实现归一化

    import sys
    class Wechat:
        def __init__(self, name):
            self.name = name
        def pay(self, money):
            print(f'{self.name}通过微信支付了{money}元。')
    class Alipay:
        def __init__(self, name):
            self.name = name
        def pay(self, money):
            print(f'{self.name}通过支付宝支付了{money}元。')
    
    
    def pay(name, price, type):
        class_name = getattr(sys.modules['__main__'], type)
        obj = class_name(name)
        obj.pay(price)
    
    pay('jason', 400, 'Wechat')
    

    反射的另一个函数 hasattr

    class A:
        def __init__(self):
            self.name = 'jason'
            self.age = 24
        def func(self):
            return 666
    j = A()
    if hasattr(j,'name'):
        print(getattr(j,'name'))
    if hasattr(j,'age'):
        print(getattr(j,'age'))
    if hasattr(j,'sex'):
        print(getattr(j,'sex'))
    
  • 相关阅读:
    [转] 64位Oracle 11g R2的客户端连接时报ORA-01019错误
    [转]Oracle11g链接提示未“在本地计算机注册“OraOLEDB.Oracle”解决方法
    [转]通过Net Manager 配置Oracle 11g本地监听服务(listener service)
    [转]jQuery Mobile动态刷新页面样式
    [转]SSIS
    [转]在SSIS中,使用“包配置”时的常见错误与解析
    使用JMH做Java微基准测试
    秒杀系统解决方案
    cookie机制和session机制
    app如何节省流量
  • 原文地址:https://www.cnblogs.com/west-yang/p/12942708.html
Copyright © 2011-2022 走看看