• 面向对象(进阶)


    类的成员

    类的成员可以分为三类:字段、方法、属性

    一:字段:

    普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同

    • 普通字段属于对象
    • 静态字段属于类

    字段的定义和使用

    class Province:
        # 静态字段
        country = '中国'
        def __init__(self,name):
            # 普通字段
            self.name = name
    # 直接访问普通字段
    obj = Province('北京')
    print obj.name
    
    # 直接访问静态字段
    print Province.country

    点睛:

    1:谁来调用:

         从上面可以看出普通字段需要通过对象来访问,静态字段通过类来调用。

    2:存储的位置

    1. 静态字段只存在把内存中一份,存在类的内存中
    2. 普通字段在每个对象中都要创建一份。

    通过类创建对象的时候,如果每个对象都具有相同的字段,那么就使用静态字段

    二:方法

    普通方法、静态方法、类方法。三种方法在内存中都属于类,区别在于调用方式不同

    • 普通方法:由对象调用,至少一个self参数,执行普通方法时,自动将调用该方法的对象赋值给self
    • 类方法:由类调用,至少一个cls参数,执行类方法时,自动将调用该方法的类赋值给cls
    • 静态方法:由类调用,无默认参数
    class Foo:
        # 初始化类
        def __init__(self):
            pass
        # 定义普通方法,至少有一个self参数
        def p(self):
            print '普通方法'
        # 定义类方法,至少有一个cls参数
        @classmethod
        def q(cls):
            print '类方法'
        # 定义静态方法
        @staticmethod
        def w():
            print '静态方法'
    # 调用普通方法
    a = Foo()
    ret = a.p()
    # print ret
    # 调用类方法
    Foo.q()
    # 调用静态方法
    Foo.w()

    点睛:

           相同点:对于所有的方法而言,均属于类中,所以在内存中也之保存一份

           不同点:方法调用者不同,调用方法时,自动传入的参数不同

    三:属性

    1:属性的基本使用

    class Foo:
        def func(self):
            # print 'func'
            return '方法调用的返回值'
    
        # 定义属性
        @property
        def prop(self):
            # print 'prop'
            return '属性调用的返回值'
    # 调用方法
    obj = Foo()
    ret = obj.func()
    print ret
    
    # 调用属性
    ret1 = obj.prop
    print ret1

    点睛:

    1. 定义时,在普通方法的基础上在上面添加@property装饰器
    2. 属性仅有一个self参数
    3. 调用时,无需括号

            方法:

                  obj = Foo()

                  ret = obj.func()

            属性:

                  obj = Foo()

                  ret = obj.prop

    属性存在的意义:访问属性时,可以制造出和访问字段完全相同的假象

    实例:

    对于主机列表页面,每次请求不可能把数据库中的所有内容都显示到页面上,而是通过分页的功能局部显示,所以在向数据库中请求数据时就要显示的指定获取从第M条到第N条的所有数据,这个分页功能包括:

    1. 根据用户请求的当前和总数据条数计算出m和n
    2. 根据m和n去数据库请求数据
    class Pager:
        def __init__(self,current_page):
            # 用户当前请求的页面
            self.current_page = current_page
            # 每页默认显示10条
            self.per_items = 10
        # 定义属性
        @property
        def start(self):
            val = (self.current_page - 1) * self.per_items
            return val
        @property
        def end(self):
            val = self.current_page * self.per_items
            return val
    # 调用属性
    p = Pager(2)
    print  p.start
    print  p.end
    # 结果:
    # 10
    # 20

    2:属性的两种定义方式

    装饰器、静态字段

    装饰器:在方法上应用装饰器

    静态字段:在类中定义值为property对象的静态字段

    装饰器方式:

    经典类,具有一种@property装饰器

    # 定义类
    class Foo:
        @property
        def fun(self):
            return 'caoxiaojian'
    # 调用属性
    obj = Foo()
    ret = obj.fun
    print ret
    # 自动执行 @property修饰的fun方法,并获取方法的返回值

    新式类,具有三种@property装饰器

    class Goods(object):
        @property
        def price(self):
            print '@property'
        @price.setter
        def price(self,value):
            print '@price.setter',value
        @price.deleter
        def price(self):
            print '@price.deleter'
    
    # 调用
    obj = Goods()
    
    obj.price               # 自动执行@property修饰的price方法,并获取方法的返回值
    obj.price = 123         # 自动执行@price.setter修饰的price方法,并将123赋值给方法的参数
    del obj.price           # 自动执行@price.deleter修饰的price方法
    执行结果:
    @property
    @price.setter 123
    @price.deleter

    注释:

    经典类中的属性只用一种访问方式,其对应被@property修饰的方法

    新式类中的属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法

    因为新式类有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为同一个属性:获取、修改、删除

    实例讲解:

    class Goods(object):
        def __init__(self):
            # 原价
            self.original_price = 100
            # 折扣
            self.discount = 0.8
    
        @property
        def price(self):
            # 实际价格 = 原价 * 折扣
            new_price = self.original_price * self.discount
            return new_price
    
        @price.setter
        def price(self,value):
            # 设置原始价格
            self.original_price = value
        @price.deleter
        def price(self,value):
            # 删除原始价格
            del self.original_price
    # 调用
    obj = Goods()
    # 获取商品价格
    obj.price
    # 设置原始价格
    obj.price = 3000
    # 删除原始价格
    del obj.price

    静态字段方式:

    创建值为property对象的静态字段

    当使用静态字段的方式创建属性时,经典类和新式类无区别

    class Foo:
        def get_bar(self):
            return 'caoxiaojian'
        BAR = property(get_bar)
    
    obj = Foo()
    # 自动调用get_bar方法,并获取方法的返回值。
    ret = obj.BAR
    print ret

    property的构造方法中有个四个参数

    • 第一个参数是方法名,调用对象.属性时自动触发执行方法
    • 第二个参数是方法名,调用对象.属性 = xxx时自动触发执行方法
    • 第三个参数是方法名,调用del 对象.属性时自动触发执行方法
    • 第四个参数是字符串,调用对象.属性.__doc__此参数是该属性的描述信息
    class Foo:
        def get_bar(self):
            return 'caoxiaojian'
        # 必须有两个参数
        def set_bar(self):
            return 'set value' + value
        def del_bar(self):
            return 'caoxiaojian===2'
        BAR = property(get_bar, set_bar, del_bar,'description......')
    
    obj = Foo()
    print obj.BAR           # 自动调用第一个参数中定义的方法:get_bar
    obj.BAR = "caogaotian"  # 自动调用第二个参数中定义的方法:set_bar方法,将"caogaotian" 当作参数传入
    print obj.BAR
    del  obj.BAR            # 自动调用第三个参数中定义的方法:del_bar
    print obj.del_bar()     
    obj.BAR.__doc__         # 自动调用第三个参数中设置的值:'description......'
    '''
    结果输出:
    caoxiaojian
    caogaotian
    caoxiaojian===2
    '''

    类成员的修饰符

    两种形式:

    1. 私有成员:只有在类的内部才能访问的方法
    2. 公有成员:在任何地方都能访问

    定义的不同:

    私有成员命名时,前面两个字符是下划线。(特殊成员除外,例如:__init__等)

    class C:
        def __init__(self):
            self.name = '公有字段'
            self.__name = '私有字段'

    私有成员和公有成员的访问限制不同

    静态字段

    • 公有静态字段:类可以访问;类内部可以访问;派生类中可以访问
    • 私有静态字段:仅类内部可以访问

    公有静态字段

    class C:
        name = '公有静态字段'
        def func(self):
            print C.name
    class D(C):
        def func_1(self):
            print C.name
    # 直接使用类访问
    C.name
    # 类内部访问
    obj = C()
    obj.func()
    # 派生类内部访问
    obj_1 = D()
    obj_1.func_1()
    '''
    结果打印:
    公有字段
    公有字段
    '''

    私有静态字段

    class C:
        __name = '公有静态字段'
        def func(self):
            print C.__name
    class D(C):
        def func_1(self):
            print C.__name
    # 类中访问
    # C.__name    # 错误
    # 类内部访问
    obj = C()
    obj.func()
    # 派生类中访问
    # obj_1 = D()    # 错误
    # obj_1.func_1()

    普通字段

    • 公有普通字段:对象、类、派生类都可以访问
    • 私有普通字段:只能在类内部访问

    公有普通字段

    class C:
        def __init__(self):
            self.foo = '公有字段'
        def func(self):
            # 在类内部调用访问
            print self.foo
    class D(C):
        def show(self):
            # 在派生类中调用访问
            print self.foo
    obj = C()
    # 通过对象访问
    print type(obj.foo)
    print  obj.foo
    print '==========='
    # 类的内部访问
    obj.func()
    print '==========='
    obj_1 = D()
    # 在派生类中访问
    obj_1.show()
    '''
    结果打印:
    <type 'str'>
    公有字段
    ===========
    公有字段
    ===========
    公有字段
    '''

    私有普通字段

    class C:
        def __init__(self):
            self.__foo = '私有普通字段'
        def func(self):
            # 类的内部调用访问
            print self.__foo
    class D(C):
        def show(self):
            # 在派生类中调用访问
            print self.__foo
    obj = C()
    # obj.__foo      # 通过对象访问:报错
    obj.func()       # 通过类内部访问
    
    obj_1 = D()
    #obj_1.show()    # 通过派生类调用访问: 报错

    类的特殊成员

    1:__doc__

    表示类的描述信息

    class C:
        """
        这是描述信息,你看什么看??
        """
        def func(self):
            pass
    print C.__doc__
    # 输出:这是描述信息,你看什么看??

    2:__module__和__class__

    __module__:表示当前操作的对象在哪个模块

    __class__: 表示当前操作的对象的类是哪一个

    在tmp模块下面有test.py和test1.py

    test.py

    class C:
        def __init__(self):
            self.name = 'caoxiaojian'

    test1.py

    from test import C
    # 根据导入的C类创建对象
    obj = C()
    # 获取对象中的模块名
    print obj.__module__   # test
    # 获取对象中的类名
    print obj.__class__    # test.C

    3:__init__

    构造方法,通过类创建对象时,自动触发执行

    class C:
        def __init__(self,name):
            self.name = name
            self.age = 18
    obj = C('caoxiaojian') # 自动执行类中的__init__方法
    print obj.name

    4:__call__

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

    点睛:

    构造方法的执行是由创建对象触发的。即:对象名 = 类名()

    __call__方法的执行由对象后面加括号触发的。即:对象()或者类名()()

    class C:
        def __init__(self):
            pass
        def __call__(self, *args, **kwargs):
            print '__call__'
    
    obj = C()      # 触发__init__
    obj()          # 触发__call__

    5:__dict__

    类或对象中的所有成员

    点睛:

    类的普通字段属于对象,类中的静态字段和方法等属于类

    class Province:
        country = 'china'
        def __init__(self,name,count):
            self.name = name
            self.count = count
    
        def func(self, *args, **kwargs):
            print 'func===func'
    
    # 获取类中的成员:静态字段和方法
    print Province.__dict__
    # {'country': 'china', '__module__': '__main__', 'func': <function func at 0x021DA7F0>, '__init__': <function __init__ at 0x021DA870>, '__doc__': None}
    
    # 调用类创建obj对象
    obj = Province('shandong',100000)
    print obj.__dict__
    # {'count': 100000, 'name': 'shandong'}
    
    # 调用类创建foo对象
    foo = Province('beijing',20000)
    print foo.__dict__
    # {'count': 20000, 'name': 'beijing'}

    类的分类:

    经典类和新式类

    # 经典类
    class func:
        def Foo(self):
            pass
    # 新式类
    class func_new(object):
        def Foo_new(self):
            pass

    点睛:

         区别:就是在类的后面加个object

    类的继承

    # 新式类
    class D(object):
    # 经典类
    #class D:
        def bar(self):
            print 'D.bar'
    class C(D):
        def bar(self):
            print 'C.bar'
    class B(D):
        pass
    class A(B,C):
        pass
    a = A()
    a.bar()
    
    '''
    经典类:深度优先  D.bar
    新式类:广度优先  C.bar
    '''

    点睛:

    经典类:深度优化

    新式类:广度优化

     

  • 相关阅读:
    21天搞定聊天机器人之{命名实体识别}
    e到底是什么?
    An example of using Pandas for regression
    Time-Series Analysis
    Multiple Regression
    Regression Analysis Using Excel
    Correlation and Regression
    Hypothesis Testing
    Sampling and Estimation
    Common Probability Distributions
  • 原文地址:https://www.cnblogs.com/caoxiaojian/p/5034696.html
Copyright © 2020-2023  润新知