Python-Basis-15th
周五,晴,记录生活分享点滴
参考博客:https://www.cnblogs.com/wupeiqi/p/4766801.html
Pyhton版本:3.5
面向对象(进阶)
类的成员
字段
普通字段
保存在对象中,执行只能通过对象访问
class Province: country = '中国' # 静态字段,属于类 def __init__(self, name): self.name = name # 普通字段,属于对象 henan = Province('河南') # 访问河南,需要通过对象访问字段 henan.name henan.name = "河南南" # 把内部的对象修改了
静态字段
保存在类中, 执行可以通过对象访问,也可以通过类访问
class Province: country = '中国' # 静态字段,属于类 def __init__(self, name): self.name = name # 普通字段,属于对象 hebei = Province('河北') hebei.name # 静态对象可以通过对象访问, print(hebei.country) # 静态对象也可以通过类访问
存储方式
小结:
- 静态字段在内存中只保存一份
- 普通字段在每个对象中都要保存一份
应用场景:
- 通过类创建对象时,如果每个对象都具有相同的字段,那么就使用静态字段
方法
种类
普通方法,保存在类中,由对象来调用;至少一个self参数:将对象赋值给参数self
类方法,保存在类中,由类直接调用;至少一个cls参数:将当前类赋值给cls
静态方法,保存在类中,由类直接调用;无默认参数
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 '静态方法' # 调用普通方法 f = Foo() f.ord_func() # 调用类方法 Foo.class_func() # 调用静态方法 Foo.static_func()
相同点:对于所有的方法而言,均属于类(非对象)中,所以,在内存中也只保存一份。
不同点:方法调用者不同、调用方法时自动传入的参数不同。
应用场景
如果对象中需要保存一些值,执行某功能时,需要使用对象中的值 ---> 普通方法
不需要任何对象中的值 ---> 静态方法
属性
属性是普通方法的变种
属性的基本使用
# ############### 定义 ############### class Foo: def func(self): pass # 定义属性 @property def prop(self): pass # ############### 调用 ############### foo_obj = Foo() foo_obj.func() foo_obj.prop #调用属性
小结:
定义时,在普通方法的基础上添加 @property 装饰器;
定义时,属性仅有一个self参数
调用时,无需括号
方法:foo_obj.func()
属性:foo_obj.prop
实例
对于主机列表页面,每次请求不可能把数据库中的所有内容都显示到页面上,而是通过分页的功能局部显示,所以在向数据库中请求数据时就要显示的指定获取从第m条到第n条的所有数据(即:limit m,n),这个分页的功能包括:
- 根据用户请求的当前页和总数据条数计算出 m 和 n
- 根据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(1) p.start 就是起始值,即:m p.end 就是结束值,即:n
类成员的修饰符
公有成员,在任何地方能访问
私有成员,在类的内部能访问
私有成员和公有成员的定义不同
私有成员命名时,前两个字符是下划线。(特殊成员除外,例如:__init__、__call__、__dict__等)
class C: def __init__(self): self.name = '公有字段' self.__foo = "私有字段"
私有成员和公有成员的访问限制不同
静态字段
公有静态字段:类可以访问;类内部可以访问;派生类中可以访问
class C: name = "公有静态字段" def func(self): print C.name class D(C): def show(self): print C.name C.name # 类访问 obj = C() obj.func() # 类内部可以访问 obj_son = D() obj_son.show() # 派生类中可以访问
私有静态字段:仅类内部可以访问
class C: __name = "私有静态字段" def func(self): print C.__name class D(C): def show(self): print C.__name C.__name # 类访问 ==> 错误 obj = C() obj.func() # 类内部可以访问 ==> 正确 obj_son = D() obj_son.show() # 派生类中可以访问 ==> 错误
普通字段
公有普通字段:对象可以访问;类内部可以访问;派生类中可以访问
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_son = D(); obj_son.show() # 派生类中访问
私有普通字段:仅类内部可以访问
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_son = D(); obj_son.show() # 派生类中访问 ==> 错误
不推荐:强制访问私有字段,可以通过 【对象._类名__私有字段名 】访问(如:obj._C__foo)
类的特殊成员
__init__
条件:类() 自动执行
class Foo: def __init__(self, name): self.name = name self.age = 23 obj = Foo('chung') # 自动执行类中的 __init__ 方法
__call__
条件:对象() or 类()() 自动执行
class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print '__call__' obj = Foo() # 执行 __init__ obj() # 执行 __call__
__int__
条件:int(对象) 获取返回值并赋值给这个对象
class Foo: def __init__(self): pass def __int__(self): return 1111 obj = Foo() r = int(obj) # int,对象,自动执行对象的 __int__方法,并将返回值赋值给int对象 print(r) # 输出:1111
__str__
条件:str() 执行str时调用的
class Foo: def __str__(self): return 'chung' obj = Foo() print obj # 输出:chung
__add__、__del__
class Foo: def __init__(self, name, age): self.name = name self.age = age def __add__(self, other):# self = obj1(alex,19); other = obj2(eric,66) # return self.age + other.age # (1)自定义返回obj1的19和obj2的66 # return Foo('tt',99) # (2)自定义返回'tt',99的对象 return Foo(obj1.name, other.age) # (3)自定义返回obj1的名字和obj2的年龄 def __del__(self): print('析构方法') # 当建立对象被销毁时,自动执行 obj1 = Foo('alex', 19) obj2 = Foo('eirc', 66) r = obj1 + obj2 # 两个对象相加时,自动执行第一个对象的__add__方法,并且将第二个对象当作参数传递进入 print(r, type(r))
__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': <function func at 0x10be30f50>, '__init__': <function __init__ at 0x10be30ed8>, '__doc__': None} obj1 = Province('HeBei',10000) print obj1.__dict__ # 获取 对象obj1 的成员 # 输出:{'count': 10000, 'name': 'HeBei'} obj2 = Province('HeNan', 3888) print obj2.__dict__ # 获取 对象obj1 的成员 # 输出:{'count': 3888, 'name': 'HeNan'}
__getitem__、__setitem__、__delitem__
用于索引操作,如字典。分别表示获取、设置、删除数据
class Foo(object): def __getitem__(self, key): print '__getitem__',key def __setitem__(self, key, value): print '__setitem__',key,value def __delitem__(self, key): print '__delitem__',key obj = Foo() result = obj['k1'] # 自动触发执行obj对象的类中的 __getitem__方法,k1当作参数传给key obj['k2'] = 'chung' # 自动触发执行 __setitem__ del obj['k1'] # 自动触发执行 __delitem__
class Foo: def __init__(self, name,age): self.name = name self.age = age def __getitem__(self, item): # return item+10 # 如果item是基本类型:int,str,索引获取 # slice对象的话,切片 if type(item) == slice: print('调用者希望内部做切片处理') else: print(item.start) print(item.stop) print(item.step) print('调用者希望内部做索引处理') def __setitem__(self, key, value): print(key,value) def __delitem__(self, key): print(key) li = Foo('chung', 18) li[123] # 索引处理 # 如果是单独的值,传递的参数是int或string类型 li[1:4:2] # 切片处理 # 如果是[1:]格式,传递的参数是slice类型 li[1:3] = [11,22] # 调用的是__setitem__ del li[1:3] # 调用的是__delitem__
__iter__
用于迭代器,之所以列表、字典、元组可以进行for循环,是因为类型内部定义了 __iter__
class Foo: def __init__(self, name,age): self.name = name self.age = age def __iter__(self): return iter([11,22,33]) # 1、执行li对象的类中的 __iter__方法,并获取其返回值 li = Foo('alex', 18) for i in li: # 2、循环上一步中返回的对象(对象iter的返回值) print(i) # 关于迭代器的几点: # 如果类中有 __iter__ 方法,创建的对象叫可迭代对象 # 可迭代对象.__iter__() 方法的返回值是迭代器 # for 循环,遇到迭代器,执行next # for 循环,遇到可迭代对象,可迭代对象.__iter__()方法,获取迭代器,执行next
__metaclass__、__new__
1. Python中一切事物都是对象
2. class Foo:
pass
obj = Foo()
# obj是对象,Foo类
# Foo类也是一个对象,type的对象
3. 类都是type类的对象 type(..)
“对象”都是类的对象 类()
# 注释解析版 class MyType(type): def __init__(self, what, bases = None, dice = None): # self=Foo super(MyType, self).__init__(what, bases, dict) def __call__(self, *args, **kwargs): # self=Foo类 obj = self.__new__(self, *args, **kwargs) # 第二阶段第二步:执行Foo的__new__方法 # obj因为下面的__new__返回,所以obj是Foo的对象 self.__init__(obj) # 第二阶段第三步:self是Foo,把obj传过来 class Foo(object, metaclass = MyType): # 第一阶段:执行MyType的__init__方法 def __init__(self, name): self.name = name def __new__(cls, *args, **kwargs): return object.__new__(cls, *args, **kwargs) # 真正创建对象的是这一句 # cls指创建了Foo的对象 obj = Foo() # 第二阶段第一步:执行MyType的__call__方法