内容简介:最终的赋值的终点是
-
补齐 python 3内容.
-
资料来源:
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000
-
更新
2019.01.17 初始化
面向对象高级编程
使用slots
- 动态语言可以随时修改和添加类与对象的属性和方法.python自然也不例外.
-
过于自由的修改,对类和对象本身不利,python中使用
__slots__
来约束这种行为.class Student(object): __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
-
限制类中只能再增加 name 和 age属性.仅对 Student 类生效,对子类无效.
使用@property
- 装饰器,不仅在函数中其作用,还可以在类中使用,限定属性的读写和范围.
-
类属性的读写,都是通过get/set方式进行,太过繁琐.Python内置的
@property
装饰器,将一个方法变为属性调用. -
示例
class Student(object): @property def score(self): return self._score @score.setter def score(self, value): if not isinstance(value, int): raise ValueError('score must be an integer!') if value < 0 or value > 100: raise ValueError('score must between 0 ~ 100!') self._score = value
最终的赋值的终点是 self._score
.操作时候直接访问 xxx.score
即可.
-
限定只读,只定义getter,不定义setter.
class Student(object): @property def birth(self): return self._birth @birth.setter def birth(self, value): self._birth = value @property def age(self): return 2015 - self._birth
birth 可写,age 只读.
多重继承
-
没什么多说的.
class Bat(Mammal, Flyable): pass
多重继承的设计,相对 java 的单继承,自由度更大,但能不能用好,取决于写代码的人.
定制类
-
类中形如
__xxx__
的变量或者函数名
str&&repr
-
__str__
和__repr__
是类/对象的打印输出. str 是调用print 函数的输出, repr 是 直接输出,常用于调试. -
示例:
class Student(object): def __init__(self, name): self.name = name def __str__(self): return 'Student object (name=%s)' % self.name __repr__ = __str__
iter&&next
-
用于 for 循环,
__iter__
用于返回一个可迭代对象(通常是自身). 同时 for 循环时,不断调用__next__
,获取下一个结果,直到遇到StopIteration
错误. -
示例:
class Fib(object): def __init__(self): self.a, self.b = 0, 1 # 初始化两个计数器a,b def __iter__(self): return self # 实例本身就是迭代对象,故返回自己 def __next__(self): self.a, self.b = self.b, self.a + self.b # 计算下一个值 if self.a > 100000: # 退出循环的条件 raise StopIteration() return self.a # 返回下一个值
getitem
-
通过
__getitem__
可以将一个对象,包装成一个list dict tuple. -
示例: list (包含不完整切片)
class Fib(object): def __getitem__(self, n): if isinstance(n, int): # n是索引 a, b = 1, 1 for x in range(n): a, b = b, a + b return a if isinstance(n, slice): # n是切片 start = n.start stop = n.stop if start is None: start = 0 a, b = 1, 1 L = [] for x in range(stop): if x >= start: L.append(a) a, b = b, a + b return L
对于切片的负数 和 [:5] 没有处理.
-
dict时,相对应的还有
__setitem__()
__delitem__()
. - 主要是python是非强类型的语言,不必非要继承并实现接口.
getattr
-
当试图调用不存在的属性和方法时,报错.此时需要找
__getattr__
. -
__getattr__
中直接返回属性和函数均可.当未匹配时返回 None.也可以自定义返回的错误类型. -
示例
class Student(object): def __getattr__(self, attr): if attr=='age': return lambda: 25 raise AttributeError('\'Student\' object has no attribute \'%s\'' % attr)
-
可以把一个类的所有属性和方法调用全部动态化处理(理解暂时不太清除,仅记录)
-
现在很多网站都搞REST API,比如新浪微博、豆瓣啥的,调用API的URL类似:
-
如果要写SDK,给每个URL对应的API都写一个方法,那得累死,而且,API一旦改动,SDK也要改。
-
利用完全动态的 getattr ,我们可以写出一个链式调用
class Chain(object): def __init__(self, path=''): self._path = path def __getattr__(self, path): return Chain('%s/%s' % (self._path, path)) def __str__(self): return self._path __repr__ = __str__
>>> Chain().status.user.timeline.list '/status/user/timeline/list'
-
无论API怎么变,SDK都可以根据URL实现完全动态的调用,而且,不随API的增加而改变!
call
-
python中函数与对象的区别十分模糊,所谓函数实际上可以看作是实现了
__call__
的一类对象,反过来一个对象通过添加(动态/静态)__call__
也可以当作函数调用. -
判断一个对象是否可当作函数调用,使用
callable
函数判断,可调用,返回True. -
示例:
class Student(object): def __init__(self, name): self.name = name def __call__(self): print('My name is %s.' % self.name)
>>> s = Student('Michael') >>> s() # self参数不要传入 My name is Michael.
枚举类
- 枚举用于限定变量的值域,防止错误的赋值导致的严重后果.Python提供了Enum类.
-
简单定义
from enum import Enum Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))
-
枚举类定义
from enum import Enum, unique @unique # 防止值重复 class Weekday(Enum): Sun = 0 # Sun的value被设定为0 Mon = 1 Tue = 2 Wed = 3 Thu = 4 Fri = 5 Sat = 6
元类
-
python作为动态语言,类和函数不是在编译时定义,而是运行时动态创建,除了编写代码创建类/函数外,python亦可以通过 type/metaclass 动态创建类/函数.
-
实际上,即使在python 中直接定义的类/函数 也是在运行时通过
type()
载入的,因此也可以直接通过type()
直接创建. -
示例:
>>> def fn(self, name='world'): # 先定义函数 ... print('Hello, %s.' % name) ... >>> Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class, 类名, 父类 ,方法 >>> h = Hello() >>> h.hello() Hello, world. >>> print(type(Hello)) <class 'type'> >>> print(type(h)) <class '__main__.Hello'>
-
metaclass
元类 ,简单来说,对象来源于类,而python中的 类 可以来源于metaclass
元类. 通过metaclass
可以非常简单的实现 对类的生成和修改. -
示例:习惯上 metaclass 的类名总是以 Metaclass 结尾
# metaclass是类的模板,所以必须从`type`类型派生: class ListMetaclass(type): # 创建类的对象,类的名称,父类 , 方法集合 def __new__(cls, name, bases, attrs): #方法添加 add 方法 attrs['add'] = lambda self, value: self.append(value) return type.__new__(cls, name, bases, attrs) class MyList(list, metaclass=ListMetaclass): pass
创建 MyList 的时候,调用了
ListMetaclass.__new__()
, 在创建时添加了 add 方法. -
示例2:ORM数据库(简)
一个ORM数据库,需要动态的根据字段,生成类,与java中不同,python 非常简单.
-
Field 基类,保存数据库的字段名和字段类型
class Field(object): def __init__(self, name, column_type): self.name = name self.column_type = column_type def __str__(self): return '<%s:%s>' % (self.__class__.__name__, self.name)
-
各个类型的Field
class StringField(Field): def __init__(self, name): super(StringField, self).__init__(name, 'varchar(100)') class IntegerField(Field): def __init__(self, name): super(IntegerField, self).__init__(name, 'bigint')
-
ModelMetaclass
class ModelMetaclass(type): def __new__(cls, name, bases, attrs): if name=='Model':#如果是 Model 基类,不修改属性等. return type.__new__(cls, name, bases, attrs) print('Found model: %s' % name) mappings = dict() for k, v in attrs.items():#保存 子类所有属性到mappings if isinstance(v, Field): print('Found mapping: %s ==> %s' % (k, v)) mappings[k] = v for k in mappings.keys():#删除子类所以属性 attrs.pop(k) attrs['__mappings__'] = mappings # 保存属性和列的映射关系 attrs['__table__'] = name # 假设表名和类名一致 return type.__new__(cls, name, bases, attrs)
-
基类Model
class Model(dict, metaclass=ModelMetaclass): def __init__(self, **kw):#接收元组 super(Model, self).__init__(**kw) def __getattr__(self, key): try: return self[key] except KeyError: raise AttributeError(r"'Model' object has no attribute '%s'" % key) def __setattr__(self, key, value): self[key] = value def save(self): fields = [] params = [] args = [] for k, v in self.__mappings__.items(): fields.append(v.name) params.append('?') args.append(getattr(self, k, None)) sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join (params)) print('SQL: %s' % sql) print('ARGS: %s' % str(args))
-
使用
class User(Model): # 定义类的属性到列的映射: id = IntegerField('id') name = StringField('username') email = StringField('email') password = StringField('password') # 创建一个实例: u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd') # 保存到数据库: u.save()
-
解
ListMetaclass.__new__()
-
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 面向Python,面向对象(基础)
- 面向Python,面向对象(基础3)
- <<深入PHP面向对象、模式与实践>>读书笔记:面向对象设计和过程式编程
- 《JavaScript面向对象精要》之六:对象模式
- 《JavaScript面向对象精要》之三:理解对象
- 面向对象的程序设计之理解对象
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。