作者: TomnJerry | 来源:发表于2018-06-26 19:09 被阅读0次

    类和对象(实例)

    1. 先将对象分类
    2. 归纳出共同特征,构建基类
    3. 构建子类,描述其不同状态(变量)和行为
    4. 创建类的实例,表示某个对象
    5. 对象通过行为触发或与其他对象交互,来实现具体功能
      如此一来,既节约了内存空间,又少写了代码。(抽象是为了偷懒,偷懒是计算机前进的动力之一)
    6. 存活的实例对象都有 “唯一“ 的ID值,可使用内置函数id()查看。(id函数用来获得对象的内存地址,并且,该ID值只能保证在某个时间段内该存活对象唯一,所以,该ID不适合作为全局身份标识)
    7. type()函数用来返回实例所属类型,不会考虑继承关系
    8. isinstance()函数判断实例是否属于特定类型,会考虑继承关系

    面向对象的三大特性:

    1. 封装
    2. 继承
    3. 多态

    经典类和新式类

    • 当类是经典类时,多继承情况下,会按照深度优先方式查找
    • 当类是新式类时,多继承情况下,会按照广度优先方式查找
    1. 如果该类或其父类继承了object类,那么该类便是新式类,否则便是经典类(新式类是推荐写法,包含更多的功能)

    类和对象在内存中的保存方式

    • 类及类中的属性和方法,在内存中只保存一份
    • 每个对象都需要在内存中保存一份(只保存对象的属性,及指向类的类对象指针)。因此,在对象执行方法时,会先通过类对象指针找到类中对应的方法,将对象当作参数传给方法的第一个参数self

    类的成员

    • 类的成员可以分为三大类:字段,方法和属性
    • 字段
      1. 普通字段(所有成员中,只有普通字段的内容是保存在对象中的,其他成员均保存在类中,在内存中只创建一份)
      2. 静态字段
    class Province:
    
        # 静态字段
        country = '中国'
    
        def __init__(self, name):
    
            # 普通字段
            self.name = name
    
    # 直接访问普通字段
    obj = Province('河北省')
    print obj.name
    
    # 直接访问静态字段
    Province.country
    
    • 方法
      1. 普通方法
      2. 类方法
      3. 静态方法
    class Foo:
     
        def __init__(self, name):
            self.name = name
     
        def ord_func(self):
            """ 定义普通方法,至少有一个self参数 """
     
            # print self.name
            print '普通方法'
     
        @classmethod
        def class_func(cls):
            """ 定义类方法,至少有一个cls参数 """
     
            print '类方法'
     
        @staticmethod
        def static_func():
            """ 定义静态方法 ,无默认参数"""
     
            print '静态方法'
     
    # 调用普通方法(自动将调用该方法的对象赋值给self)
    f = Foo()
    f.ord_func()
     
    # 调用类方法(自动将调用该方法的类复制给cls)
    Foo.class_func() # 推荐
    f.class_func()
     
    # 调用静态方法(由类调用)
    Foo.static_func() # 推荐
    f.static_func
    
    • 属性
      1. 普通属性(属性存在意义是:访问属性时可以制造出和访问字段完全相同的假象)(属性由方法变种而来,如果Python中没有属性,方法完全可以代替其功能)
    # ############### 定义 ###############
    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(1)
    p.start # 就是起始值,即:m
    p.end # 就是结束值,即:n
    
    # 定义时,在普通方法的基础上添加 @property 装饰器;
    # 定义时,属性仅有一个self参数
    # 调用时,无需括号,自动执行属性,并获取属性的返回值
    # 方法:foo_obj.func()
    # 属性:foo_obj.prop
    
    1. 定义属性的两种方式
    • 装饰器定义(新式类有三种属性定义装饰器,经典类只有@property一种)
    # ############### 定义 ###############
    class Goods(object):
     
        @property
        def price(self):
            print '@property'
     
        @price.setter
        def price(self, value):
            print '@price.setter'
     
        @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 方法
    

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

    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.deltter
        def price(self, value):
            del self.original_price # del删除的是变量,解除变量和数据的引用,而不是删除数据
     
    obj = Goods()
    obj.price         # 获取商品价格
    obj.price = 200   # 修改商品原价
    del obj.price     # 删除商品原价
    
    • 静态字段定义(当使用静态字段的方式创建属性时,经典类和新式类无区别)
    class Foo:
     
        def get_bar(self):
            return 'wupeiqi'
     
        BAR = property(get_bar)
     
    obj = Foo()
    reuslt = obj.BAR        # 自动调用get_bar方法,并获取方法的返回值
    print reuslt
    

    property的构造方法中有个四个参数
    第一个参数是方法名,调用 对象.属性 时自动触发执行方法
    第二个参数是方法名,调用 对象.属性 = XXX 时自动触发执行方法
    第三个参数是方法名,调用 del 对象.属性 时自动触发执行方法
    第四个参数是字符串,调用 对象.属性.doc ,此参数是该属性的描述信息

    class Foo:
     
        def get_bar(self):
            return 'wupeiqi'
     
        # *必须两个参数
        def set_bar(self, value): 
            return 'set value' + value
     
        def del_bar(self):
            return 'wupeiqi'
     
        BAR = property(get_bar, set_bar, del_bar, 'description...')
     
    obj = Foo()
     
    obj.BAR              # 自动调用第一个参数中定义的方法:get_bar
    obj.BAR = "alex"     # 自动调用第二个参数中定义的方法:set_bar方法,并将“alex”当作参数传入
    del Foo.BAR          # 自动调用第三个参数中定义的方法:del_bar方法
    obj.BAE.__doc__      # 自动获取第四个参数中设置的值:description...
    

    由于静态字段方式创建属性具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除

    class Goods(object):
     
        def __init__(self):
            # 原价
            self.original_price = 100
            # 折扣
            self.discount = 0.8
     
        def get_price(self):
            # 实际价格 = 原价 * 折扣
            new_price = self.original_price * self.discount
            return new_price
     
        def set_price(self, value):
            self.original_price = value
     
        def del_price(self, value):
            del self.original_price
     
        PRICE = property(get_price, set_price, del_price, '价格属性描述...')
     
    obj = Goods()
    obj.PRICE         # 获取商品价格
    obj.PRICE = 200   # 修改商品原价
    del obj.PRICE     # 删除商品原价
    

    类成员的修饰符

    • 公有成员,在任何地方都能访问
    • 私有成员,只有在类的内部才能访问
      私有成员和公有成员的定义不同:私有成员命名时,前两个字符是下划线。(特殊成员除外,例如:initcalldict等)
    class C:
     
        def __init__(self):
            self.name = '公有字段'
            self.__foo = "私有字段"
    
    class C:
    
        name = "公有静态字段"
        __name = "私有静态字段"
        
        def __init__(self):
            ...
    

    类的特殊成员

    # __doc__ 类的描述信息
    class Foo:
        """ 描述类信息写在这里 """
     
        def func(self):
            pass
    print Foo.__doc__
    #输出:类的描述信息
    
    # __module__ 表示当前操作的对象在哪个模块
    # __class__ 表示当前操作的对象的类是什么
    
    # __init__ 构造方法,创建对象时自动执行
    
    # __del__ 析构方法,对象在内存中释放时自动触发执行
    
    # __call__ call方法通过对象后加括号执行
    class Foo:
     
        def __init__(self):
            pass
     
        def __call__(self, *args, **kwargs):
     
            print '__call__'
     
    obj = Foo() # 执行 __init__
    obj()       # 执行 __call__
    Foo()()     # 执行 __call__
    
    # __dict__ 显示类或对象所拥有的成员
    class Province:
     
        country = 'China'
     
        def __init__(self, name, count):
            self.name = name
            self.count = count
     
        def func(self, *args, **kwargs):
            print 'func'
     
    # 获取类的成员,即:静态字段、方法
    print Province.__dict__
    # 输出:{'country': 'China', '__module__': '__main__', 'func': , '__init__': , '__doc__': None}
     
    obj1 = Province('HeBei',10000)
    print obj1.__dict__
    # 获取 对象obj1 的成员
    # 输出:{'count': 10000, 'name': 'HeBei'}
     
    obj2 = Province('HeNan', 3888)
    print obj2.__dict__
    # 获取 对象obj2 的成员
    # 输出:{'count': 3888, 'name': 'HeNan'}
    
    # __str__ 打印对象默认输出该方法的返回值
    

    Python中一切皆是对象

    • 类本身也是对象,并且类是由type类创建的
    • 类的创建也可以通过type类的构造函数创建
    def func(self):
        print 'hello xiaozhupeiqi'
     
    Foo = type('Foo',(object,), {'func': func})
    #type第一个参数:类名
    #type第二个参数:当前类的基类
    #type第三个参数:类的成员
    

    相关文章

      网友评论

          本文标题:

          本文链接:https://www.haomeiwen.com/subject/dvsmyftx.html