【发布时间】:2014-01-08 07:37:54
【问题描述】:
在下面的代码中,为什么g.__int 等于0 而不是1 最后,而g.__dictionary 和g.__list 都保留了它们在装饰器中的值?
为什么我可以将列表/字典作为属性添加到装饰器内部的函数中,然后在装饰器外部访问它,但我不能对整数做同样的事情?
这里有一些代码来说明:
import functools
def dictify(func):
func.__dictionary = { 0 : 0 }
@functools.wraps(func)
def _func(*args, **kwds):
func.__dictionary[0] += 1
print(' Incremented __dictionary, now __dictionary = {0}'.format(str(func.__dictionary)))
return func(*args, **kwds)
return _func
def listify(func):
func.__list = [1, 2, 3]
@functools.wraps(func)
def _func(*args, **kwds):
func.__list.append(0)
print(' Appended 0 to __list, now __list = {0}'.format(str(func.__list)))
return func(*args, **kwds)
return _func
def intify(func):
func.__int = 0
@functools.wraps(func)
def _func(*args, **kwds):
func.__int += 1
print(' Incremented __int, now __int = {0}'.format(func.__int))
return func(*args, **kwds)
return _func
def g():
return 'pennyroyal tea'
print('*** UNMODIFIED ***')
print('g() returns \'{0}\''.format(g()))
print('id(g) = {0}'.format(id(g)))
g = dictify(g)
print('*** DICTIFIED ***')
print('g() returns \'{0}\''.format(g()))
print('g.__dictionary = {0}'.format(str(g.__dictionary)))
print('id(g) = {0}'.format(id(g)))
g = listify(g)
print('*** LISTIFIED ***')
print('g() returns \'{0}\''.format(g()))
print('g.__dictionary = {0}'.format(str(g.__dictionary)))
print('g.__list = {0}'.format(str(g.__list)))
print('id(g) = {0}'.format(id(g)))
g = intify(g)
print('*** INTIFIED ***')
print('g() returns \'{0}\''.format(g()))
print('g.__dictionary = {0}'.format(str(g.__dictionary)))
print('g.__list = {0}'.format(str(g.__list)))
print('g.__int = {0}'.format(str(g.__int)))
print('id(g) = {0}'.format(id(g)))
这给出了以下输出:
*** UNMODIFIED ***
g() returns 'pennyroyal tea'
id(g) = 139861398390976
*** DICTIFIED ***
Incremented __dictionary, now __dictionary = {0: 1}
g() returns 'pennyroyal tea'
g.__dictionary = {0: 1}
id(g) = 139861398391096
*** LISTIFIED ***
Appended 0 to __list, now __list = [1, 2, 3, 0]
Incremented __dictionary, now __dictionary = {0: 2}
g() returns 'pennyroyal tea'
g.__dictionary = {0: 2}
g.__list = [1, 2, 3, 0]
id(g) = 139861398391216
*** INTIFIED ***
Incremented __int, now __int = 1
Appended 0 to __list, now __list = [1, 2, 3, 0, 0]
Incremented __dictionary, now __dictionary = {0: 3}
g() returns 'pennyroyal tea'
g.__dictionary = {0: 3}
g.__list = [1, 2, 3, 0, 0]
g.__int = 0
id(g) = 139861398391336
可以看到,在装饰器内部,func.__int 的值打印为1,但在装饰器外部,g.__int 是默认的0,而g.__dictionary 和g.__list 保留它们的值在装饰器内部和外部引用时。
注意:id(g) 调用表明用dictify()、listify() 和intify() 进行装饰都会返回新对象,说明函数是不可变的。 (见我的详细解释here)
这个问题是基于我之前的一个here。它的答案满足了我的实际需要,但我的“为什么”本能不会把这个放在一边。 :)
【问题讨论】:
标签: python function attributes decorator