python工程实践·笔记
原文链接
业务代码的一些常见原则
- 可读性第一定理
- KISS原则,Keep It Simple, Stupid
- 开发可以工作的、最简单的解决方案。除非有不可辩驳的原因,否则不要使用模式、原则和高难度技术之类的东西
- DRY原则,Don’t Repeat Yourself
- YAGNI,You Aren’t Gonna Need It
- 应尽量避免使用幻数(也叫常数,例如,(if status=1))
面向对象编程
python变量的下划线
- xx: 公有变量
- _x: 单前置下划线,私有化属性或方法,from somemodule import *禁止导入,类对象和子类可以访问
- __xx:双前置下划线,避免与子类中的属性命名冲突,无法在外部直接访问(名字重整所以访问不到)
- _xx_:双前后下划线,用户名字空间的魔法对象或属性。例如:_init_ , __ 不要自己发明这样的名字
- xx_:单后置下划线,用于避免与Python关键词的冲突
类和实例
# __init__()的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
# 有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去
访问限制
# 如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线,使其成为私有变量,只能通过get()/set()访问属性
bart = Student('Bart Simpson', 59)
bart.name = 'daemon'
bart.score = 99
# 所以,定义类:
class Student(object):
def __init__(self, name, score):
self.__name = name
self.__score = score
# 原理解释:不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,所以,仍然可以通过_Student__name来访问__name变量。但是,强烈不建议!!!!!!
_slots_
# 限制class实例能添加的属性,注意:仅对当前类实例起作用,对继承的子类是不起作用。
class Student(object):
__slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
@property
# 负责把一个方法变成属性调用
class Student(object):
@property
def score(self):
return self._score
定制类
_str_
_iter_
class Fib(object):
def __init__(self):
self.a, self.b = 0, 1 # 初始化两个计数器a,b
# 实现for.in 循环,不断调用迭代对象的__next__()获取下一个值,直到遇到StopIteration错误时退出循环
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 # 返回下一个值
for n in Fib():
print(n)
_getitem_
class Fib(object):
# 像list那样按照下标取出元素
def __getitem__(self, n):
a, b = 1, 1
for x in range(n):
a, b = b, a + b
return a
_setitem_
把对象视作list或dict来对集合赋值
_delitem_
用于删除某个元素
_getattr_
当调用不存在的属性时,比如score,Python解释器会试图调用__getattr__(self, 'score')来尝试获得属性
作用就是,可以针对完全动态的情况作调用。
例如,动态URL,链式调用URL:
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'