如何用 name 属性实例化一个 io.TextIOWrapper 对象?
How to instantiate an io.TextIOWrapper object with a name attribute?
import sys
print(sys.stdin)
print(type(sys.stdin))
print(sys.stdin.name)
print(sys.stdin.__dict__)
以上执行后,输出结果如下:
<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>
<class '_io.TextIOWrapper'>
<stdin>
{'mode': 'r'}
所以从上面的代码片段和输出中,我可以看到 name
是表示 sys.stdin
的 _io.TextIOWrapper
实例的一个属性。从 io.TextIOWrapper
上的文档(例如,通过 $ pydoc io.TextIOWrapper
),它确实将 name
列为数据描述符。但是,无论出于何种原因,name
都没有在其 __dict__
.
中显示为项目
当我手动创建 io.TextIOWrapper
的实例时使用例如:
import io
a = io.TextIOWrapper(io.BytesIO())
print(a)
a.name
<_io.TextIOWrapper encoding='UTF-8'>
被打印出来。但是 a.name
行抛出错误:AttributeError: '_io.BytesIO' object has no attribute 'name'
; AttributeError
是我预料的,没想到它说是一个 _io.BytesIO
对象。
然后我尝试创建一个子类并手动附加一个 name
属性,如下所示:
import io
class NamedTextIOWrapper(io.TextIOWrapper):
def __init__(self, buffer, name=None, **kwargs):
self.name = name
io.TextIOWrapper.__init__(self, buffer, **kwargs)
input = io.BytesIO('abc')
stdin = NamedTextIOWrapper(input, name='<stdin>', encoding='utf-8')
print(stdin.name)
然而这会遇到:AttributeError: attribute 'name' of '_io.TextIOWrapper' objects is not writable
.
理想情况下,我还希望能够在手动实例化的 io.TextIOWrapper
对象中维护 sys.stdin
实例中看似可用的 mode
属性。并且对于 sys.stdout
等价物,我认为除了 name
应该设置为 '<stdout>'
和 mode
应该设置为 'w'
之外,它们是一样的。
当请求 name
属性时,您可以使用 returns 对象属性字典的 name
键覆盖 __getattribute__
方法:
class NamedTextIOWrapper(io.TextIOWrapper):
def __init__(self, buffer, name=None, **kwargs):
vars(self)['name'] = name
super().__init__(buffer, **kwargs)
def __getattribute__(self, name):
if name == 'name':
return vars(self)['name']
return super().__getattribute__(name)
这样:
input = io.BytesIO(b'abc')
stdin = NamedTextIOWrapper(input, name='<stdin>', encoding='utf-8')
print(stdin.name)
输出:
<stdin>
import sys
print(sys.stdin)
print(type(sys.stdin))
print(sys.stdin.name)
print(sys.stdin.__dict__)
以上执行后,输出结果如下:
<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>
<class '_io.TextIOWrapper'>
<stdin>
{'mode': 'r'}
所以从上面的代码片段和输出中,我可以看到 name
是表示 sys.stdin
的 _io.TextIOWrapper
实例的一个属性。从 io.TextIOWrapper
上的文档(例如,通过 $ pydoc io.TextIOWrapper
),它确实将 name
列为数据描述符。但是,无论出于何种原因,name
都没有在其 __dict__
.
当我手动创建 io.TextIOWrapper
的实例时使用例如:
import io
a = io.TextIOWrapper(io.BytesIO())
print(a)
a.name
<_io.TextIOWrapper encoding='UTF-8'>
被打印出来。但是 a.name
行抛出错误:AttributeError: '_io.BytesIO' object has no attribute 'name'
; AttributeError
是我预料的,没想到它说是一个 _io.BytesIO
对象。
然后我尝试创建一个子类并手动附加一个 name
属性,如下所示:
import io
class NamedTextIOWrapper(io.TextIOWrapper):
def __init__(self, buffer, name=None, **kwargs):
self.name = name
io.TextIOWrapper.__init__(self, buffer, **kwargs)
input = io.BytesIO('abc')
stdin = NamedTextIOWrapper(input, name='<stdin>', encoding='utf-8')
print(stdin.name)
然而这会遇到:AttributeError: attribute 'name' of '_io.TextIOWrapper' objects is not writable
.
理想情况下,我还希望能够在手动实例化的 io.TextIOWrapper
对象中维护 sys.stdin
实例中看似可用的 mode
属性。并且对于 sys.stdout
等价物,我认为除了 name
应该设置为 '<stdout>'
和 mode
应该设置为 'w'
之外,它们是一样的。
当请求 name
属性时,您可以使用 returns 对象属性字典的 name
键覆盖 __getattribute__
方法:
class NamedTextIOWrapper(io.TextIOWrapper):
def __init__(self, buffer, name=None, **kwargs):
vars(self)['name'] = name
super().__init__(buffer, **kwargs)
def __getattribute__(self, name):
if name == 'name':
return vars(self)['name']
return super().__getattribute__(name)
这样:
input = io.BytesIO(b'abc')
stdin = NamedTextIOWrapper(input, name='<stdin>', encoding='utf-8')
print(stdin.name)
输出:
<stdin>