类和对象(实例)
- 先将对象分类
- 归纳出共同特征,构建基类
- 构建子类,描述其不同状态(变量)和行为
- 创建类的实例,表示某个对象
- 对象通过行为触发或与其他对象交互,来实现具体功能
如此一来,既节约了内存空间,又少写了代码。(抽象是为了偷懒,偷懒是计算机前进的动力之一) - 存活的实例对象都有 “唯一“ 的ID值,可使用内置函数id()查看。(id函数用来获得对象的内存地址,并且,该ID值只能保证在某个时间段内该存活对象唯一,所以,该ID不适合作为全局身份标识)
- type()函数用来返回实例所属类型,不会考虑继承关系
- isinstance()函数判断实例是否属于特定类型,会考虑继承关系
面向对象的三大特性:
- 封装
- 继承
- 多态
经典类和新式类
- 当类是经典类时,多继承情况下,会按照深度优先方式查找
- 当类是新式类时,多继承情况下,会按照广度优先方式查找
- 如果该类或其父类继承了object类,那么该类便是新式类,否则便是经典类(新式类是推荐写法,包含更多的功能)
类和对象在内存中的保存方式
- 类及类中的属性和方法,在内存中只保存一份
- 每个对象都需要在内存中保存一份(只保存对象的属性,及指向类的类对象指针)。因此,在对象执行方法时,会先通过类对象指针找到类中对应的方法,将对象当作参数传给方法的第一个参数self
类的成员
- 类的成员可以分为三大类:字段,方法和属性
- 字段
- 普通字段(所有成员中,只有普通字段的内容是保存在对象中的,其他成员均保存在类中,在内存中只创建一份)
- 静态字段
class Province:
# 静态字段
country = '中国'
def __init__(self, name):
# 普通字段
self.name = name
# 直接访问普通字段
obj = Province('河北省')
print obj.name
# 直接访问静态字段
Province.country
- 方法
- 普通方法
- 类方法
- 静态方法
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
- 属性
- 普通属性(属性存在意义是:访问属性时可以制造出和访问字段完全相同的假象)(属性由方法变种而来,如果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
- 定义属性的两种方式
- 装饰器定义(新式类有三种属性定义装饰器,经典类只有@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 # 删除商品原价
类成员的修饰符
- 公有成员,在任何地方都能访问
- 私有成员,只有在类的内部才能访问
私有成员和公有成员的定义不同:私有成员命名时,前两个字符是下划线。(特殊成员除外,例如:init、call、dict等)
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第三个参数:类的成员
网友评论