欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

程序员文章站 2022-07-14 10:04:37
...

类和对象(实例)

  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第三个参数:类的成员