用None来描述具有动态默认值的参数
2018-11-04 本文已影响0人
叶田的学习笔记
下面的代码用来描述两个不同学生选择不同课程的场景。
class Student(object):
def __init__(self,name,course=[]):
self.name = name
self.course = course
def addcourse(self,coursename):
self.course.append(coursename)
def printcourse(self):
for item in self.course:
print(item)
stuA = Student('wang')
stuA.addcourse('english')
stuA.addcourse('math')
print(stuA.name + "'s courses:")
stuA.printcourse()
print('----------------')
stuB = Student('li')
stuB.addcourse('chinese')
stuB.addcourse('music')
print(stuB.name + "'s courses:")
stuB.printcourse()
结果:
wang's courses:
english
math
----------------
li's courses:
english
math
chinese
music
问题:li同学多了两门课。
原因:在实例化两个对象的时候,这两个对象被分配了不同的内存空间,并且调用__init__()函数进行初始化。但由于__init__()函数的第二个参数是个默认参数,默认参数在函数被调用的时候胡仅仅评估一次,以后都会使用第一次评估的结果。因此,实际上对象空间里面的course所指向的是list的地址,每次操作的实际上是list所指向的具体列表。
要解决上述例子中的问题,最好是传入None作为默认参数,在创建对象的时候动态生成列表。
def __init(self,name,course=None):
self.name = name
if course is None:
course=[]
self.course = course
再举一个例子:
在打印日志消息的时候,把相关事件的记录时间也标注在消息里。
from datetime import datetime
import time
def log(message,when=datetime.now()):
print('{}:{}'.format(when,message))
log('Hi,there!')
time.sleep(0.1)
log('Hi,again!')
结果 :
2018-11-04 23:05:40.244085:Hi,there!
2018-11-04 23:05:40.244085:Hi,again!
两条消息的时间戳是一样的。
将参数值设置为None,就没问题了。
def log(message,when=None):
when = datetime.now() if when is None else when
print('{}:{}'.format(when,message))