类和对象(实例)

  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第三个参数:类的成员
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容