https://bop.mol.uno/ 已读
- python 类变量与对象变量
Class Variable 是共享的,它们可以被属于该类的所有实例访问。该类变量只拥有一个副本,当任何一个对象对类变量作出改变时,发生的变动将在其它所有实例中都会得到体现。
Object variable 由类的每一个独立的对象或实例所拥有。在这种情况下,每个对象都拥有属于它自己的字段的副本,也就是说,它们不会被共享,也不会以任何方式与其它不同实例中的相同名称的字段产生关联。
比如:
class Robot:
# 一个类变量
population = 0
def __init__(self, name):
self.name = name
print("(Initializing {})".format(self.name))
#这个population是通过Robot类名调用
Robot.population += 1
def die(self):
print("{} is being destroyed!".format(self.name))
Robot.population -= 1
if Robot.population == 0:
print("{} was the last one.".format(self.name))
else:
print("There are still {:d} robots working.".format(
Robot.population))
def say_hi(self):
print("Greetings, my masters call me {}.".format(self.name))
#类方法
#how_many 实际上是一个属于类而非属于对象的方法。
#这就意味着我们可以将它定义为一个 classmethod(类方法) 或是一个 staticmethod(静态方法),这取决于我们是否需要知道这一方法属于哪个类。
#由于我们已经引用了一个类变量,因此我们使用 classmethod
@classmethod
def how_many(cls):
print("We have {:d} robots.".format(cls.population))
- 注意当一个对象变量与一个类变量名称相同时,类变量将会被隐藏。
- 除了 Robot.popluation,我们还可以使用 self.class.population,因为每个对象都通过 self.class 属性来引用它的类。
- 只能使用 self 来引用同一对象的变量与方法。这被称作属性引用(Attribute Reference)。
- 所有的类成员都是公开的。但有一个例外:如果你使用数据成员并在其名字中使用双下划线作为前缀,形成诸如 __privatevar 这样的形式,Python 会使用名称调整(Name-mangling)来使其有效地成为一个私有变量。
- Exception handler
with - 在 try 块中获取资源,然后在 finally 块中释放资源,用with可以更优雅的完成。
f = open("poem.txt")
try:
yield f
finally:
f.close()
with open("poem.txt") as f:
for line in f:
print(line, end='')
- Lambda
lambda 语句可以创建一个新的函数对象。从本质上说,lambda 需要一个参数,后跟一个表达式作为函数体,这一表达式执行的值将作为这个新函数的返回值。
points = [{'x': 2, 'y': 3},
{'x': 4, 'y': 1}]
points.sort(key=lambda i: i['y'])
#按y值排序字典
4.列表推导(List Comprehension)
用于从一份现有的列表中得到一份新列表。
listone = [2, 3, 4]
listtwo = [2*i for i in listone if i > 2]
print(listtwo)
在本案例中,当满足了某些条件时(if i > 2),我们进行指定的操作(2*i),以此来获得一份新的列表。要注意到原始列表依旧保持不变。
- 使用列表推导的优点在于,当我们使用循环来处理列表中的每个元素并将其存储到新的列表中时时,它能减少样板(Boilerplate)代码的数量。
5.装饰器
装饰器(Decorators)是应用包装函数的快捷方式。这有助于将某一功能与一些代码一遍又一遍地“包装”。
举个例子,我为自己创建了一个 retry 装饰器,这样我可以将其运用到任何函数之中,如果在一次运行中抛出了任何错误,它就会尝试重新运行,直到最大次数 5 次,并且每次运行期间都会有一定的延迟。
from time import sleep
from functools import wraps
import logging
logging.basicConfig()
log = logging.getLogger("retry")
def retry(f):
@wraps(f)
def wrapped_f(*args, **kwargs):
MAX_ATTEMPTS = 5
for attempt in range(1, MAX_ATTEMPTS + 1):
try:
return f(*args, **kwargs)
except:
log.exception("Attempt %s/%s failed : %s",
attempt,
MAX_ATTEMPTS,
(args, kwargs))
sleep(10 * attempt)
log.critical("All %s attempts failed : %s",
MAX_ATTEMPTS,
(args, kwargs))
return wrapped_f
counter = 0
@retry
def save_to_database(arg):
print("Write to a database or make a network call or etc.")
print("This will be automatically retried if exception is thrown.")
global counter
counter += 1
# 这将在第一次调用时抛出异常
# 在第二次运行时将正常工作(也就是重试)
if counter < 2:
raise ValueError(arg)
if __name__ == '__main__':
save_to_database("Some bad value")
- yield
https://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/
带有 yield 的函数在 Python 中被称之为 generator(生成器)
fibonachi
class Fab(object):
def __init__(self, max):
self.max = max
self.n, self.a, self.b = 0, 0, 1
def __iter__(self):
return self
def next(self):
if self.n < self.max:
r = self.b
self.a, self.b = self.b, self.a + self.b
self.n = self.n + 1
return r
raise StopIteration()
Fab 类通过 next() 不断返回数列的下一个数,内存占用始终为常数:
def fab(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
for n in fab(5)
#这里就会用到iterater b
print(n)
这样用了yield就更加简洁