zoukankan      html  css  js  c++  java
  • day07_雷神_面向对象进阶

    day07

    1.接口类(抽象类)

    接口类和抽象类是一种规范,写代码时的规范。

    两个思想: 一个是统一接口,一个是定义规则。

    最终版本:接口类,抽象类,是一种规范,写代码时的规范 强制性的规定。
    
    from abc import ABCMeta,abstractmethod
    class Payrole(metaclass=ABCMeta):  # 抽象类或者接口类,制定规范,统一方法名。
        @abstractmethod
        def pay(self): pass
    
    class QQpay(Payrole):
        def pay(self,money):
            print('您已经通过qq支付了%s元' %money)
    
    class Alipay(Payrole):
        def pay(self, money):
            print('您已经通过支付宝支付了%s元' % money)
    
    class Wechatpay(Payrole):
        def pay(self, money):
            print('您已经通过支付宝支付了%s元' % money)
    
    def pay(obj,money):
        obj.pay(money)
    
    # a = QQpay()
    # b = Alipay()
    c = Wechatpay()
    # pay(a,100)  # 归一化设计,统一你的支付方式
    # pay(b,1200)
    pay(c,10000)
    

    2. 多态,鸭子类型

    Python默认就支持多态,自带多态,也叫鸭子类型。

    python 对于一些相似的方法,不用强制规定,都是约定俗成。
    

    3. 封装

    广义封装: 封装到对象中的属性(普通字段),静态字段等。

    狭义封装: 私有性封装。

    私有:包括私有静态字段(私有静态变量),私有普通字段(私有对象属性),私有方法。

    3.1 私有静态字段

    class Person:
        country = 'China' # 公有静态字段(公有静态变量)
        __name = 'oldboy' # 私有静态字段(私有静态变量)
        __age = 1000 # 私有静态字段(私有静态变量)
        def func1(self):
            return self.__name
    print(Person.country)
    在类的外部不能调用
    print(Person.__name)
    p1 = Person()
    
    
    print(p1.__name)
    print(Person.__dict__['_Person__name'])
    print(Person._Person__name)  虽然可以,但是一定不要这样访问。
    在类的内部可以访问
    print(p1.func1())
    

    派生类也不可访问父类的私有静态字段。

    class God:
        __kind = '黄种人'  # _God__kind
    
    class Person(God):
        country = 'China' # 公有静态字段(公有静态变量)
        __name = 'oldboy' # 私有静态字段(私有静态变量)
        __age = 1000 # 私有静态字段(私有静态变量)
        # def func1(self):
        #     return self.__name
        def func2(self):
            return self.__kind  # _Person__kind
    
    p1 = Person()
    print(p1.func2())
    

    总结: 私有静态字段:类内部可以访问,父类以及类的外部不能访问。

    只要类执行,将类的内容加载到内存时,发现有 __变量名 这样的Python解释器自动将__变量名转化成_类名__变量名
    
    类执行,所有的字段和函数名(即内存地址)都会被加载。
    

    3.2 私有普通字段

    class Person:
        def __init__(self,name,age):
            self.name = name  # 公有普通字段 (公有普通对象属性)
            self.__age = age  # 私有普通字段 (私有普通对象属性)
        def func1(self):
            return self.__age
    p1 = Person('alex', 40)
    print(p1.name)
    print(p1.func1())
    

    私有成员用在哪里?

    示例一: 密码加密

    class Cipher_encryption:
    
        def __init__(self,username,password):
            self.username = username
            self.__password = self.__encryption(password)
    
        def __encryption(self,pwd):
            '''
            加密处理
            :param pwd:
            :return:
            '''
            return '%s hao123' % pwd
    
    user1 = Cipher_encryption('alex', 'alexsb')
    print(user1.username)
    # print(user1.password)
    print(user1.__dict__)
    对于只想让类内部使用的成员,要设置成私有成员。
    

    示例二:

    class A:
        a = 1
        b = 2
        def __init__(self):
            c = 666
    a1 = A()
    a1.a = 333
    a1.b = 555
    print(a1.a,a1.b,a1.c)
    
    c = 666 不在a1对象的内存地址中,虽然执行了__init__方法,但是没有self.c = 666.
    

    示例三: 类中遇到双下线加变量,就自动改名字。

    class A:
        def __init__(self):
            self.__func()
        def __func(self):
            print("in A")
    
    class B(A):
        def __func(self):
            print("in B")
    
    b = B()
    这时候输出的是A,因为__func函数改名字了。
    

    4. 字段,方法,普通方法,静态方法,类方法,属性

    4.1 普通方法

    一般由对象调用。
    

    4.2 属性

    @property

    class People:
        def __init__(self, name, weight, height):
            self.name=name
            self.__weight=weight
            self.__height=height
    
        @property
        def bmi(self):
            return self.__weight / self.__height**2
    
    p1 = People('天', 95,1.83)
    print(p1.bmi)
    # property 属性将你的一些方法伪装成属性,虽然在代码上没有什么提高,让其看起来更合乎情理.
    

    @ property 下的@方法.setter,修改

    class Goods:
    
        def __init__(self,name,origin_price,discount):
            self.name = name
            self.__origin_price = origin_price
            self.__discount = discount
    
        @property
        def price(self):
            return self.__origin_price*self.__discount
    
        @price.setter
        def price(self,new_price):
            self.__origin_price = new_price
    
    p1 = Goods('apple',5,0.8)
    print(p1.price)
    p1.price = 8
    print(p1.price)
    

    @ property 下的@方法.deleter,删除

    class People:
        def __init__(self, name, age, sex):
            self.name = name
            self.__age = age
            self.__sex = sex
    
        @property
        def age(self):
            return self.__age
    
        @age.setter
        def age(self,new_age):
            if type(new_age) == int:
                self.__age = new_age
            else:
                print('请输入一个整数')
    
        @age.deleter
        def age(self):
            print(666)
    
    p1 = People('天', 28, '男')
    print(p1.name)
    p1.name = '地'
    print(p1.name)
    print(p1.age)  # p1.age 触发 @property装饰的方法
    p1.age = '1234' # p1.age = '1234'  触发 @age.setter装饰的方法
    print(p1.age)
    del p1.age  # del p1.age 触发  @age.deleter装饰的方法
    

    4.3 类方法

    一般是由类名调用.有些情况,对于类内部的方法,无需对象直接调用,而类名直接调用即可。

    @classmethod

    class Goods:
    
        __discount = 0.8
    
        def __init__(self,name,origin_price):
            self.name = name
            self.__origin_price = origin_price
    
        @property
        def price(self):
            return self.__origin_price * Goods.__discount
    
        @classmethod
        def discount(cls,new_discount):
            Goods.__discount = new_discount
    
    p1 = Goods('apple',5)
    print(p1.price)
    # p1.discount(0.85)
    Goods.discount(0.85)
    print(p1.price)
    

    4.4 静态方法

    不需要传入对象,和类名,直接调用即可.

    class A:
    
        def __init__(self):
            pass
    
        @staticmethod
        def login(username,password):
            print(username,password)
    
    
    A.login('alex',123)
    

    5. 其他成员及方法

    isinstance() 对象是否属于这个类,或者这个类血缘关系.

    class C: pass
    class A(C): pass
    class B(A): pass
    
    abj = B()
    print(isinstance(abj,B))  #True
    print(isinstance(abj,A))  #True
    print(isinstance(abj,C))  #True
    

    issubclass() 判断 第一类是第二个类的后代.True

    class C: pass
    
    class A: pass
    
    class B(A,C): pass
    
    print(issubclass(A,B)) #False
    print(issubclass(B,C)) #True
    

    反射:非常重要。

    01.类中的反射:

    这个方法是用dict方法,通过字典的key来查询。

    class A:
        role = 'Teacher'
    
        def func(self):
            print(666)
    
    msg = input('>>>')
    print(A.role)
    print(A.__dict__[msg])
    

    getattr方法

    getattr(A,msg)  # *****
    getattr(A,msg)(111)  # 通过字符串 去到 类名 中获取对应的值.
    print(getattr(A,msg))
    hasattr() *****
    print(hasattr(A,msg))
    if hasattr(A,msg):
        print(getattr(A,msg))
    else:
        print('不存在此值')
    
    setattr() 增加或者修改 **
    setattr(A,'name','alex')
    setattr(A,'role','student')
    print(A.__dict__)
    
    delattr(A,'role')  # 删除*
    print(A.__dict__)
    

    02.对象中的反射

    在python 中一切皆对象,凡是通过 什么.什么 通过 反射都能取到

    class A:
        role = 'Teacher'
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    
    a1 = A('太白', 18)
    
    print(hasattr(a1,'name'))			True
    print(hasattr(a1,'sex'))			False
    print(getattr(a1, 'role'))			Teacher
    

    03. 模块中

    一个模块就是一个文件

    import time

    print(time.time())
    print(getattr(time,'time'))
    print(getattr(time,'time')())

    oldboy模块

    def func():
    name = 'alexsb'
    print('此函数完成的是打印666功能')

    class A:
    role = 'Teacher'
    def func1(self):
    print(666)

    反射示例:

    import oldboy
    
    print(getattr(oldboy,'func'))
    getattr(oldboy,'func')()
    方式一
    print(getattr(oldboy,'A'))
    print(getattr(oldboy,'A').role)
    getattr(oldboy,'A').func1(11)
    
    方式二
    print(getattr(getattr(oldboy,'A'),'role'))
    

    04. 当前模块中

    def login():
        print(666)
    
    msg = input('>>>')
    import sys
    
    getattr(sys.modules[__name__],msg)()
    print(globals())  #{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001B465F3A3C8>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:/Users/Administrator/PycharmProjects/oldboy/day07/day07/07 其他成员及方法.py', '__cached__': None, 'login': <function login at 0x000001B465E31E18>, 'msg': 'login', 'sys': <module 'sys' (built-in)>}
    
    print(locals())
    print(dir())  # ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'login', 'msg', 'sys']
    
    print(__name__)  #__main__
    

    其他方法:

    01. __len __

    class A:
        def __init__(self):
            self.a = 1
            self.b = 2
    
        def __len__(self):
            return len(self.__dict__)
    
    a = A()
    print(len(a))
    

    02. __hash __

    class A:
    def __init__(self):
        self.a = 1
        self.b = 2
    
    def __hash__(self):
        return hash(str(self.a)+str(self.b))
    a = A()
    print(hash(a))
    

    03. __ str__

    类中如有__str__方法,print(对象),str(a) print('%s' % a),打印该对象时,默认输出该方法的返回值。

    class A:
        def __init__(self):
            pass
        def __str__(self):
            return '太白'
    a = A()
    print(a,type(a))  太白 <class '__main__.A'>
    print(str(a),type(str(a)))  太白 <class 'str'>
    print('%s' % a)  太白
    

    04. __ repr __

    和str一样

    class A:
        def __init__(self):
            pass
        def __repr__(self):
            return '太白'
    a = A()
    print(a)
    print(repr(a))
    print('%r'%a)
    

    05. __call __

    对象后面加括号,触发执行。

    注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 call 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

    class Foo:
    
        def __init__(self):
            pass
    
        def __call__(self, *args, **kwargs):
            print('__call__')
    
    
    obj = Foo()  # 执行 __init__
    obj()  # 执行 __call__
    

    06. __eq __

    07. __ del__

    析构方法,当对象在内存中被释放时,自动触发执行。

    注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

    08. __ new__

    实例化对象的时候自动触发。

    单例模式:

    class A:
        __instance = None
        def __new__(cls, *args, **kwargs):
            if cls.__instance is None:
                obj = object.__new__(cls)
                cls.__instance = obj
            return cls.__instance
    

    09. item系列

    class Foo:
        def __init__(self,name):
            self.name=name
    
        def __getitem__(self, item):
            print(self.__dict__[item])
    
        def __setitem__(self, key, value):
            print(key,value)
            self.__dict__[key]=value
        def __delitem__(self, key):
            print('del obj[key]时,我执行')
        #     self.__dict__.pop(key)
    
    f1 = Foo('sb')
    # f1['name']  # 对对象进行字典式的查询操作 触发 __getitem__
    # f1['age'] = 18  # 对对象进行字典式的更改 触发 __setitem__
    f1['age1']=19
    # del f1.age1
    del f1['age']  # 对对象进行字典式的del删除 触发 __delitem__
    f1['name']='alex'
    print(f1.__dict__)
    My name is 侯冰雷 ~~欢迎转载 ~~欢迎关注 ~~欢迎留言
  • 相关阅读:
    Git上传文件、文件夹到github
    Git管理修改、撤销修改、删除文件
    Git使用教程之从远程库克隆项目(四)
    Git使用教程之在github上创建项目(三)
    Git使用教程之SSH连接方式配置(二)
    Git使用教程之新手也能看懂(一)
    JS字符串截取 “指定字符” 前面和后面的内容!
    vue.js 实现点击展开收起动画
    最简单的手机预览WEB移动端网页的方法
    vue-cli中浏览器图标的配置
  • 原文地址:https://www.cnblogs.com/houbinglei/p/9268845.html
Copyright © 2011-2022 走看看