zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    LeetCode 81 Search in Rotated Sorted Array II(循环有序数组中的查找问题)
    LeetCode 80 Remove Duplicates from Sorted Array II(移除数组中出现两次以上的元素)
    LeetCode 79 Word Search(单词查找)
    LeetCode 78 Subsets (所有子集)
    LeetCode 77 Combinations(排列组合)
    LeetCode 50 Pow(x, n) (实现幂运算)
    LeetCode 49 Group Anagrams(字符串分组)
    LeetCode 48 Rotate Image(2D图像旋转问题)
    LeetCode 47 Permutations II(全排列)
    LeetCode 46 Permutations(全排列问题)
  • 原文地址:https://www.cnblogs.com/yoyowin/p/13502659.html
Copyright © 2011-2022 走看看