用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))
上一篇下一篇

猜你喜欢

热点阅读