• python面向对象进阶和模块初识


    本篇内容主要是面向对象的进阶和模块的初识,主要包括如下内容:接口类和抽象类、封装、类方法、静态方法、属性、反射、特殊方法、序列化模块、random模块。

    1.接口类抽象类

    '''
    整体说明:
    01 在python中的接口类和抽象类的含义是一样的,其他语言中接口类和抽象类的定义不同。
    02 python中的接口类定义:制定一个规则,让其他人按照我的规则去写程序。(约定俗成,有些野蛮程序员可能不会遵循)
    03 python接口类的形式:(约定俗成的规范,即如果在一个类中出现如下形式,则说明是python的接口类定义)
    # class payment:  # 类名根据实际的需求进行定义
    #     def func(self): # 函数的参数根据实际的需求进行补充和完善;函数名根据实际的要求进行定义。
    #         pass
    04 python接口类(强制规范)形式:
    # from abc import ABCMeta, abstractmethod  # 该处引用是必须的,如果强制规范的接口类,必须进行引用。
    # class payment(metaclass=ABCMeta):   # 类名根据实际的需求进行定义
    #     @abstractmethod
    #     def func(self):  # 函数的参数根据实际的需求进行补充和完善;函数名根据实际的要求进行定义。
    #         pass
    05 在编写代码的时候需要遵循“归一化”设计,即比如线上支付,支付的手段有QQ、微信、支付宝三种支付方式,最后统一的调用
       支付接口的时候,尽量定义统计的调用方式进行(下面会有具体的示例展示)。
    '''
    # 1.支付方式不统一
    class QQpay:
        def pay(self, money):
            print('QQ支付了%s钱' % money)
    
    
    class Alipay:
        def pay(self, money):
            print('支付宝支付了%s钱' % money)
    
    
    a1 = QQpay()
    a1.pay(100)
    b1 = Alipay()
    b1.pay(200)
    
    # 2.统一支付方式:归一化设计
    
    class QQpay:
        def pay(self, money):
            print('QQ支付了%s钱' % money)
    
    
    class Alipay:
        def pay(self, money):
            print('支付宝支付了%s钱' % money)
    
    
    def pay(obj, money):  # 归一化设计,设计统一的调用方式
        obj.pay(money)
    
    
    a1 = QQpay()
    b1 = Alipay()
    pay(a1, 100)
    pay(b1, 200)
    
    # 3.接口类定义:制定一个规则,让其他人按照我的规则去写程序。
    class payment:   # 定义接口类,让所有人都遵循这个方式进行定义支付类。
        def pay(self, money):
            pass
    
    
    class QQpay(payment):
        def pay(self, money):
            print('QQ支付了%s钱' % money)
    
    
    class Alipay(payment):
        def pay(self, money):
            print('支付宝支付了%s钱' % money)
    
    
    class Wechat(payment):
        def fuqian(self, money):
            print('微信支付了%s钱' % money)
    
    
    def pay(obj, money):  # 归一化设计
        obj.pay(money)
    
    # 4.接口类定义(强制规范):
    from abc import ABCMeta, abstractmethod   # 通过引用实现强制规范的接口类
    
    
    class payment(metaclass=ABCMeta):
        @abstractmethod  # 引用装饰器,实现强制规范接口类。
        def pay(self, money):
            pass
    
    
    class QQpay(payment):
        def pay(self, money):
            print('QQ支付了%s钱' % money)
    
    
    class Alipay(payment):
        def pay(self, money):
            print('支付宝支付了%s钱' % money)
    
    # 错误写法
    class Wechat(payment):
        def fuqian(self, money):  # 该处未按照标准的格式来,所以,在调用该类的时候会报错,应该讲方法fuqian修改为pay即可
            print('微信支付了%s钱' % money)
    
    # 正确写法
    class Wechat(payment):
        def pay(self, money):  # 该处未按照标准的格式来,所以,在调用该类的时候会报错,应该讲方法fuqian修改为pay即可
            print('微信支付了%s钱' % money)
    
    
    
    def pay(obj, money):  # 归一化设计
        obj.pay(money)
    
    
    w = Wechat()
    pay(w, 100)

    2.封装

    '''
    01 封装的定义
        (1)广义的封装:将一些内容放到一个‘容器’中。
        (2)狭义的封装:私有
    02 私有成员:
        (1)私有成员包括私有变量,私有对象属性,私有方法。
        (2)私有成员类外面不能访问,派生类不可以访问,类内可以访问。
    03 类的结构:静态变量(属性,字段)、私有静态变量、动态普通方法、私有方法、特殊方法(双下划下方法)、私有对象属性
                 属性、类方法、静态方法。
    '''
    
    # 01 类的结构
    class B:
        country = 'China'  # 静态变量(属性,字段)
        __name = 'alex'  # 私有静态变量
        
        def func(self):  # 动态普通方法
            pass
        
        def __func(self):  # 私有方法
            pass
        
        def __init__(self, name, age):  # 特殊方法:双下方法
            self.name = name
            self.__age = age  # 私有对象属性
        
        @property  # 属性
        def f1(self):
            pass
        
        @classmethod  # 类方法
        def func2(self):
            pass
        
        @staticmethod  # 静态方法
        def func3(self):
            pass
    
    # 02 私有成员:类外面不能访问,派生类不可以访问,类内可以访问。
    class A:
        country = 'China'  # 静态变量(属性,字段)
        __name = 'alex'  # 私有静态变量
        
        def __init__(self, name, age):
            self.name = name
            self.__age = age
        
        def func(self):  # 动态普通方法
            print(self.__name)
        
        def __func(self):  # 私有方法
            pass
    
    
    class B(A):
        def func2(self):
            print(self.__name)
    
    
    obj = A('二狗', 18)
    print(obj.country)  # 类外面可以访问
    # print(obj.__name)  # 私有:类外面不可以访问
    
    obj.func()  # 私有:类内面可以访问
    
    o1 = B('脸哥', 25)
    o1.func2()  # 私有:派生类不可以访问
    
    obj = A('二狗', 18)
    print(A.__dict__)
    # print(obj._A__name)

    3.类方法

    '''
    整体说明:
    01 必须通过类的调用,而且此方法的意义在于对类里面的变量或者方法进行修改添加。
    02 类方法通过使用装饰器“@classmethod”来标记,同时装饰器下面的方法中的变量必须默认为“cls”。
    '''
    
    # 01 类方法说明:
    class B:
        country = 'China'  # 静态变量(属性,字段)
    
        def func(self):  # 动态普通方法
            pass
    
        def __init__(self, name, age):  # 特殊方法:双下方法
            self.name = name
    
        @classmethod  # 类方法
        def func2(cls):  # 对B类进行修改,封装了2个属性,即area和name
            cls.area = '东北'
            cls.name = '马玉刚'
    print(B)
    '''
    运行结果:<class '__main__.B'>
    '''
    print(B.__dict__)
    '''
    运行结果:
    {'__module__': '__main__', 'country': 'China', 'func': <function B.func at 0x0000000001E9DF28>,
    '__init__': <function B.__init__ at 0x0000000001EA2048>, 'func2': <classmethod object at 0x0000000001E9E9E8>,
     '__dict__': <attribute '__dict__' of 'B' objects>, '__weakref__': <attribute '__weakref__' of 'B' objects>,
     '__doc__': None}
    '''
    B.func2()
    print(B.__dict__)
    '''
    运行结果:'
    {'__module__': '__main__', 'country': 'China', 'func': <function B.func at 0x0000000001E9DF28>,
    '__init__': <function B.__init__ at 0x0000000001EA2048>, 'func2': <classmethod object at 0x0000000001E9E9E8>,
     '__dict__': <attribute '__dict__' of 'B' objects>, '__weakref__': <attribute '__weakref__' of 'B' objects>,
     '__doc__': None, 'area': '东北', 'name': '狗哥'}
    '''
    
    # 02 类方法应用:统计类实例对象的个数
    
    class C:
        count = 0
        
        def __init__(self):  # 实例化对象默认必须执行__init__函数
            C.cou()
        
        @classmethod
        def cou(cls):
            cls.count += 1
    
    
    obj = C()
    obj = C()
    obj = C()
    obj = C()
    obj = C()
    obj = C()
    obj = C()
    obj = C()
    obj = C()
    obj = C()
    obj = C()
    print(C.count)
    
    
    '''
    运行结果:11
    '''

    4.静态方法

    '''
    整体说明:
    01 静态方法定义:在类中,一个不依赖类以及对象的一个普通函数。
    02 静态方法作用:保证代码的一致性,可调控性,整洁性。
    '''
    
    # 1. 静态方法示例
    class C:
        def __init__(self):
            pass
    
        @staticmethod
        def func(*args, **kwargs):  # 该方法可以独立与类C存在,不依赖类和对象存在。
            print(666)
    C.func()
    c1 = C()
    c1.func()
    
    # 2. 静态方法示例
    import time
    
    
    class TimeTest(object):
        def __init__(self, hour, minute, second):
            self.hour = hour
            self.minute = minute
            self.second = second
    
        @staticmethod  # 静态方法
        def showTime():
            return time.strftime("%H:%M:%S", time.localtime())
    
    '''
    说明:
    01 将以下方法移动至TimeTest仍可以正常执行,与类和对象无关。
     def showTime():
            return time.strftime("%H:%M:%S", time.localtime())
    '''

    5.属性

    '''
    整体说明:
    01 property:是将方法伪装成为一个属性。
    02 property引用形式:在方法前加上装饰器@property 进行伪装即可。
    03 property的作用:代码层面上没有提升,但是他会让你的代码看起来更合理。在对象进行方法调用的时候,无需在方法名后加括号即可调用方法。
    04 property的装饰器是成对出现的:@property 、@AAA.setter、 @AAA.deleter,其中@property最为常用和重要。
        (1)@property:对象执行get的时候运行装饰器下的方法。
        (2)@AAA.setter:对象执行set的时候运行该装饰器下的方法。
        (3)@AAA.deleter:对象执行删除的时候运行该装饰器下的方法。
    05 在进行setter和deleter的时候,方法名和调用装饰器的方法名必须保持一致。
    '''
    
    # 01 属性:为什么要进行伪装。
    '''
    需求:测试人体的BMI值
    '''
    
    
    class B:
        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
    
    
    gouge = B('马玉刚', 90, 1.78)
    print(gouge.bmi)
    
    # 说明:bmi看起来应该是一个名字,但是你用一个方法去实现,所以为了符合逻辑性,增加属性装饰器@property来进行。
    # 由于伪装成为属性,所以在调用方法的时候无需在方法名后面加括号。
    
    # 02 属性的说明
    class Foo:
    
        def __init__(self,name):
            self.name = name
        @property   # ***
        def AAA(self):
            print('get的时候运行我啊')
    
        @AAA.setter  # *
        def AAA(self,value):
    
            print('set的时候运行我啊')
    
        @AAA.deleter  # *
        def AAA(self):
            print('delete的时候运行我啊')
    obj = Foo('alex')
    obj.name = '太白'
    print(obj.name)
    # del obj.name
    # print(obj.name)
    obj.AAA = 666  # 对伪装的属性进行改值是就会调用 def AAA(self,value):
    del obj.AAA  # 对伪装的属性进行detele的时候进行运行@AAA.deleter下的方法。
    
    # 03 属性应用1:
    '''
    需求:
    01 苹果的原始价位8元,折扣价格:0.8折,求苹果的售卖单价。
    02 苹果的原始价格7元,折扣不变,求苹果的售卖店家。
    03 原始价格和折扣都是私有变量。
    '''
    
    
    class Product:
        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
    
    
    apple = Product('苹果', 8, 0.95)
    print(apple.price)
    apple.price = 7
    print(apple.price)

    6.反射

    '''
    整体说明:
    01 反射的定义:通过字符串去操作对象(实例化对象,类,模块)
    02 反射应用场景如下:
        (1)反射可以对实例化对象使用。
        (2)反射可以对类使用。
        (3)反射可以对当前模块使用。
        (4)反射可以对其他模块使用。
    03 反射的方法:
       (1)hasattr() :判断是否存在某个变量或者方法。 ***
       (2)getattr() :以字符串的形式获取某个变量或者方法。 ***
       (3)setattr() :对某个变量或者方法进行设置。  *
       (4)delattr() :对某个变量或者方法进行删除。*
    04 isinstance:判断的是obj是否是此类或者此类的子孙类实例化出来的对象。 # isinstance(obj, B)
    05 issubclass: 判断B是否是A的子类或者孙类。 # issubclass(B, A)
    '''
    # # 01 isinstance:判断的是obj是否是此类或者此类的子孙类实例化出来的对象。
    class A: pass
    
    
    class B(A): pass
    
    
    obj = B()
    print(isinstance(obj, B))  # True
    print(isinstance(obj, A))  # True
    
    # 02 issubclass:判断B是否是A的子类或者孙类。 # issubclass(B, A)
    class C: pass
    
    
    class A(C): pass
    
    
    class B(A): pass
    
    
    abj = B()
    
    print(issubclass(B, A))  # True
    print(issubclass(B, C))  # True
    
    #  03 反射对实例化对象应用的示例。
    class A:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    
    obj = A('脸哥', 27)
    
    ret = getattr(obj, 'name', None)  # getattr获取对象中的name,如果没有返回None
    print(hasattr(obj, 'age'))   # hasattr判断对象中是否有age,有返回True,没有返回False
    print(ret)
    if hasattr(obj, 'name'):
        ret = getattr(obj, 'name')
    
    setattr(obj, 'sex', '')  # 设置
    print(getattr(obj, 'sex'))
    
    delattr(obj, 'name')  # 删除
    print(obj.__dict__)
    
    #  03 反射对类应用的示例。
    
    class A:
        name = 'alex'
        
        def __init__(self):
            pass
        
        def func(self):
            print('IN func')
    
    
    ret = input('>>>>')  # 输入func,并且将func赋值给ret
    f1 = getattr(A, ret)(1)  # 通过getattr执行func方法,方法名+()调用方法执行方法,()中的1是需要给方法中传进入一个变量,变量任意。
    
    '''
    说明:
    通过类名调用类中的方法时其实是在执行函数func,并不是类中的方法,所以并不会自动赋值给self,所以需要是手动赋值,可以是任意值。
    '''
    
    #  04 反射在当前模块中的应用。
    def func():
        print('in func')
    
    
    import sys
    
    current_module = sys.modules[__name__]
    
    getattr(current_module, 'func')()
    
    # 05 反射在对其他模块(文件)应用的示例。
    import fs  # fs为自定义模块
    
    print(getattr(fs, 'n1'))
    ret = getattr(fs, 'func')
    ret()
    
    # 方法一:
    clas = getattr(fs, 'A')
    print(clas.name)
    
    # 方法二:
    print(getattr(fs.A, 'name'))
    getattr(fs.A, 'func2')(1)

    7.特殊方法

    '''
    整体说明:
    01 单例设计模式:让一个类的实例化对象有且只有一个 ***
    02 __init__和__new__的先后顺序。
        (1)第一步:__new__先要new出一个对象(__new__方法在object类中默认的方法)
        (2)第二步:根据创建出的类,通过__init__进行属性的封装。
    03 __call__方法。
    04 __item__系列:对一个对象进行类似于字典的操作,就会触发__item__系列的某个方法。 ***
        (1)__getitem__
        (2)__setitem__
        (3)__delitem__
    05 __str__:遇到print()后即触发该方法执行。
    06 __repr__:遇到print()后即触发该方法执行。
    07 __call__:对象+(),触发该方法。
    '''
    
    # 01 __str__:遇到print()后即触发该方法执行。
    class A:
        def __init__(self):
            pass
    
        def __str__(self):
            print(666)
            return '马玉刚'
    
    
    a = A()
    ret = '姓名:%s' % a
    print(ret)
    
    '''
    运行结果:
    666
    姓名:马玉刚
    '''
    
    # 02 __repr__:遇到print()后即触发该方法执行。
    
    class A:
        def __init__(self):
            pass
    
        def __repr__(self):
            return '马玉刚'
    
    
    a = A()
    print('%r' % a)  # 马玉刚
    
    # 03 __call__:对象+(),触发该方法。
    
    class Foo:
    
        def __init__(self):
            pass
    
        def __call__(self, *args, **kwargs):
            print(args)
            print('__call__')
    
    obj = Foo()
    obj('WuSir', 'alex')  # 对象() 触发 __call__()方法
    
    '''
    运行结果:
    ('WuSir', 'alex')
    __call__
    '''
    
    # 04 单例设计模式
    
    '''未采用单例设计模式'''
    class A:
        pass
    
    
    ret = A()
    ret1 = A()
    print(ret, ret1)
    
    '''
    运行结果:两个不同的地址
    <__main__.A object at 0x00000000021DE908> <__main__.A object at 0x00000000021DE940>
    '''
    
    '''采用单例设计模式,单例设计模式有7种方式,以下是一种常用的单例设计模式'''
    class A:
        __instance = None
    
        def __new__(cls, *args, **kwargs):
            if cls.__instance is None:
                obj = object.__new__(cls)
                cls.__instance = obj
            return cls.__instance
    
    
    ret1 = A()
    ret2 = A()
    ret3 = A()
    print(ret1, ret2, ret3)
    
    '''
    运行结果:同一地址
    <__main__.A object at 0x00000000021DE978> <__main__.A object at 0x00000000021DE978> <__main__.A object at 0x00000000021DE978>
    '''
    
    
    # 05 __item__系列 __getitem__  __setitem__ __delitem__ ***
    # 对一个对象进行类似于字典的操作,就会触发__item__系列的某个方法。
    class Foo:
        def __init__(self, name):
            self.name = name
        
        def __getitem__(self, item):
            print('__getitem__此方法执行了')
            return self.__dict__[item]
        
        def __setitem__(self, key, value):
            print('__setitem__此方法执行了')
            self.key = value
        
        def __delitem__(self, key):
            print('del obj[key]时,我执行')
            self.__dict__.pop(key)
            
            def __delattr__(self, item):
                print('del obj.key时,我执行')
                self.__dict__.pop(item)
    
    f = Foo('alex')
    print(f['name'])  # f[name]属于查的方式,所以触发了__getitem__方法。
    f['age'] = 25  # 触发了__setitem__的方法。
    del f['name']  # 触发了__delitem__方法
    print(f.__dict__)

    8.序列化模块

    '''
    整体说明:
    01 模块定义:一个py文件就是一个模块。
    02 模块的分类:
        (1)内置模块: time os random shelve re 等等。
        (2)拓展模块:beautifulsoup iteat等大神写的模块。
        (3)自定义模块:自己整理的模块。
    03 序列化模块:
        (1)JSON:适用于所有语言。
            (1)网络传输:dumps loads
            (2)文件写入:dump load
        (2) pickle 只用于Python语言之间的传输,包含所有的python支持的数据类型。
        (3)shelve :直接对文件句柄操作,就可以存入数据。
    04  python和JSON的转换
    
    #     +-------------------+---------------+
    #     | Python | JSON |
    #     += == == == == == == == == == += == == == == == == == +
    #     | dict | object |
    #     +-------------------+---------------+
    #     | list, tuple | array |
    #     +-------------------+---------------+
    #     | str | string |
    #     +-------------------+---------------+
    #     | int, float | number |
    #     +-------------------+---------------+
    #     | True | true |
    #     +-------------------+---------------+
    #     | False | false |
    #     +-------------------+---------------+
    #     | None | null |
    #     +-------------------+---------------+
    
    '''
    import json
    import pickle
    
    # 01  JSON序列化
    # dumps loads  # 网络传输
    dic = {'name': '二狗', 'age': 25, 'sex': ''}
    ret = json.dumps(dic, ensure_ascii=False)  # 序列化过程 : 就是变成一个特殊的字符串
    respon = json.loads(ret)  # 反序列化:将序列化的特殊字符串反解成原来的类型。
    print(ret, type(ret))
    print(dic)
    print(respon, type(respon))
    
    # dump load  写入常规文件
    dic = {1: {'username': '二狗1', 'password': 123},
           2: {'username': '二狗2', 'password': 123},
           3: {'username': '二狗3', 'password': 123},
           }
    f = open('json_file', 'w')
    json.dump(dic, f)  # dump方法接收一个文件句柄,直接将字典转换成json字符串写入文件
    f.close()
    
    f = open('json_file')
    dic2 = json.load(f)  # load方法接收一个文件句柄,直接将文件中的json字符串转换成数据结构返回
    print(dic2, type(dic2))
    f.close()
    print(type(dic2), dic2)
    
    # 02 pickle 只用于Python语言之间的传输,包含所有的python支持的数据类型。
    dic = {'name': '二狗', 'age': 25, 'sex': ''}
    ret = pickle.dumps(dic)
    respon = pickle.loads(ret)
    print(ret)
    print(respon)
    
    #  dump load # 写入文件  (这个不仅可以写常规的数据,还可以将对象写入)
    
    class A:
        name = 'alex'
        
        def func(self):
            print(666)
    
    
    obj = A()
    f = open('pickle_file', 'wb')
    pickle.dump(obj, f)
    f.close()
    
    f = open('pickle_file', 'rb')
    ret = pickle.load(f)
    print(ret.name)
    ret.func()
    f.close()
    
    # 03 shelve
    import shelve
    
    f = shelve.open('shelve_file')
    f['key'] = {'int': 10, 'float': 9.5, 'string': 'Sample data'}  # 直接对文件句柄操作,就可以存入数据
    f.close()
    
    import shelve
    
    f1 = shelve.open('shelve_file')
    existing = f1['key']  # 取出数据的时候也只需要直接用key获取即可,但是如果key不存在会报错
    f1.close()
    print(existing)

    9.random模块

    '''
    整体说明:
    01 print(random.random())  # 随机在0~1之间的float
    02 print(random.uniform(1,10)) # 1 ~10 浮点型
    03 print(random.randint(1,10)) # 1~10 之间的整数  ***
    04 print(random.randrange(1,10,2)) # 大于等于1且小于10之间的奇数(2是步长)
    05 print(random.choice([1, '23', [4,5]]))  # 多选择一  ***
    06 print(random.sample([1,'23',[4,5], 'alex'],2)) #  列表元素 任意2个组合
    07  random.shuffle(item) # 打乱次序  ***
    '''
    
    '''
    需求:生成5位随机验证码
    开发思路:
    0~9 随机选一个
    a~z 随机选一个
    两个选一个
    '''
    import random
    
    
    def code():
        codes = ''
        for i in range(5):
            num = str(random.randint(0, 9))
            char1 = chr(random.randint(97, 122))
            char2 = chr(random.randint(65, 96))
            c1 = random.choice([num, char1, char2])
            codes += c1  # 字符串拼接
        return codes
    
    
    print(code())
    
    # 说明:chr(code)是根据asscall值获得对应的字符。

    ref : https://www.cnblogs.com/mayugang/p/9980394.html

  • 相关阅读:
    Omi新成员omi-router正式发布
    Omi架构与React Fiber
    Omi框架Store体系的前世今生
    Omi v1.0震撼发布
    omi-cli新版发布-升级webpack2和支持sass生成组件局部CSS
    Omi应用md2site-0.5.0发布-支持动态markdown拉取解析
    Omi应用md2site发布-markdown转网站利器
    AlloyTouch之无限循环select插件
    Omi教程-插件体系
    AlloyTouch之select选择插件
  • 原文地址:https://www.cnblogs.com/yoyowin/p/13502659.html
Copyright © 2020-2023  润新知