为啥从 Python 中的对象继承,在不指定父对象时更改 __dict__ 的类型不会? [复制]
Posted
技术标签:
【中文标题】为啥从 Python 中的对象继承,在不指定父对象时更改 __dict__ 的类型不会? [复制]【英文标题】:Why does inherting from object in Python, change they type of the __dict__ when not specifying a parent does not? [duplicate]为什么从 Python 中的对象继承,在不指定父对象时更改 __dict__ 的类型不会? [复制] 【发布时间】:2013-10-04 20:16:37 【问题描述】:我有一段简单的代码试图在 Python 中为file
提供便利。
class File:
def __init__(this, *args):
this._file = file(*args)
def __del__(this):
this._file.close()
def createCallForwarder(method):
return lambda obj,*args: method(obj._file, *args)
_dict = file.__dict__
for (k,v) in zip(_dict.keys(), _dict.values()):
if not (k.startswith('__') and k.endswith('__')):
if v.__class__.__name__ == 'method_descriptor':
File.__dict__[k] = createCallForwarder(v)
# get the repr method
File.__repr__ = createCallForwarder(dict_proxy['__repr__'])
如果我将File
更改为从object
继承,它不会让我分配方法。
为什么不一样?
【问题讨论】:
天哪,你想用你的代码实现什么?为什么不使用file
的子类,或者使用__getattr__
挂钩来代理方法?
如果您想在新样式类中做同样的事情,请使用 setattr
:setattr(File, k, createCallForwarder(v))
谢谢!这正是我所需要的。我对 Python 没有太多经验。我只是想获得一个自行关闭的 File 对象,所以我不必关心。我不想泄露文件对象。
只是一个风格提示:按照惯例,Python 使用 self
而不是 this
。
@AadityaKalsi:Python 文件对象已经这样做了。他们拥有自己的__del__
处理程序。
【参考方案1】:
您根本不应该直接访问__dict__
。
改为使用__getattr__
method 代理对底层self._file
对象的调用:
class File(object):
def __init__(self, *args):
self._file = open(*args)
def __getattr__(self, name):
return getattr(self._file, name)
我还将代码切换为最佳实践;使用self
代替this
并使用open()
代替file()
。
对于新式对象(继承自object
),使用setattr()
设置任意属性。但是,不需要使用呼叫转发器包装器。您也可以采用self._file
的绑定 方法并将它们直接设置在self
上:
class File(object):
def __init__(self, *args):
self._file = open(*args)
for name in dir(self._file):
setattr(self, name, getattr(self._file, name))
如果你想要的只是一个在垃圾收集时自动关闭的文件对象,那么你就白费了很多麻烦。 Python 文件对象已经有一个__del__
处理程序正是这样做的。它只是没有作为显式的 __del__
函数公开,而是 C 实现使用 deallocation function 在释放时调用 close_the_file(f)
。
然而,最佳实践是使用文件对象作为上下文管理器,使用with
statement:
with open(somefilename) as fileobj:
# do all sorts with fileobj
# here, fileobj will have been closed automatically.
引用file.close()
documentation:
从 Python 2.5 开始,如果使用 with 语句,您可以避免显式调用此方法。例如,下面的代码会在
with
块退出时自动关闭f:from __future__ import with_statement # This isn't required in Python 2.6 with open("hello.txt") as f: for line in f: print line,
【讨论】:
谢谢!这很有帮助,我更喜欢 getattr 方式。我唯一遇到的问题是它不能很好地与 readline 一起用于自动完成。我有这个实现的原因是因为我有其他对象可能多次写入同一个文件,并且 open
多次是昂贵的。
@AadityaKalsi:在这种情况下,代理文件对象不会为您买任何任何东西。文件对象已经在 CPython 中自动关闭。
@AadityaKalsi:您可以实现 __dir__
method 或许有助于自动完成。【参考方案2】:
我只是想获得一个会自行关闭的 File 对象
使用with statement
将(除其他外)为您关闭文件:
with open('somefile.txt') as the_file:
for line in the_file:
# do something with line
# Once outside the with block, the file is automatically closed
print('somefile.txt is closed here')
【讨论】:
以上是关于为啥从 Python 中的对象继承,在不指定父对象时更改 __dict__ 的类型不会? [复制]的主要内容,如果未能解决你的问题,请参考以下文章