Python str子类表示一个非实字符串的值
我是python的新手。正在扩展旧模块。到目前为止,它有一个返回Python str子类表示一个非实字符串的值,python,string,class,inheritance,subclass,Python,String,Class,Inheritance,Subclass,我是python的新手。正在扩展旧模块。到目前为止,它有一个返回str(阻塞shell命令的输出)的函数。现在,我需要该函数也能够返回一个对象,以便以后可以对其执行操作(检查非阻塞shell命令的输出)。因此,函数现在返回我的类的一个实例,为了向后兼容,我从str子类化了它。然而,问题是,当这样一个对象被传递到os.path.isdir时,它总是返回False,即使字符串是有效的路径 import os class ShellWrap(str): def __new__(cls,
str
(阻塞shell命令的输出)的函数。现在,我需要该函数也能够返回一个对象,以便以后可以对其执行操作(检查非阻塞shell命令的输出)。因此,函数现在返回我的类的一个实例,为了向后兼容,我从str
子类化了它。然而,问题是,当这样一个对象被传递到os.path.isdir时,它总是返回False,即使字符串是有效的路径
import os
class ShellWrap(str):
def __new__(cls, dummy_str_value, process_handle):
return str.__new__(cls,"")
def __init__(self, dummy_str_value, process_handle):
self._ph = process_handle
self._output_str = ""
def wait_for_output(self):
# for simplicity just do
self._output_str = "/Users"
def __str__(self):
return str(self._output_str)
def __repr__(self):
return str(self._output_str)
def __eq__(self,other):
if (isinstance(other, str)):
return other == str(self._output_str)
else:
return super().__eq__(self,other)
>>> obj = ShellWrap("",None)
>>> obj.wait_for_output()
>>> print(type(obj))
... <class '__main__.ShellWrap'>
>>> print (ShellWrap.__mro__)
... <class '__main__.ShellWrap'>
(<class '__main__.ShellWrap'>, <class 'str'>, <class 'object'>)
>>> print(type(obj._output_str))
... <class 'str'>
>>> print(obj)
... /Users
>>> print(obj._output_str)
... /Users
>>> obj == "/Users"
... True
似乎还有一个dunder我没能实现。但是哪个呢
然而,我确实在调试器中看到了一些奇怪的东西。当我把手表放在obj
上时,它说它属于类str
,但调试器显示的值没有引号(与其他“纯”str不同)。
在调试器中手动向字符串添加引号可以使其工作,但我想编辑字符串可能会创建一个新对象,这次是纯str
我错过了什么
Edit:在意识到(参见接受的答案)我试图做的是不可能的之后,我决定挑战必须将
str子类化的决定。所以现在我的类没有继承任何东西。它只实现了\uuuuu str\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu!显然,只要str继承存在,它就会获得优先权,dunders就不会被调用,并且它会欺骗一些库去获取str值的底层C存储
使用字符串的C代码访问由str
类管理的实际字符串数据,而不是您正在编写的方法。它不关心您是否将另一个字符串作为属性附加到对象,或者您是否覆盖了一组方法。它比您的对象更接近str.\uuuuuuwhater.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu(您的对象)
,尽管它
在本例中,相关的C代码是os.stat
调用os.path.isdir
委托给的,但是几乎任何使用字符串的东西都将使用用C编写的东西,在某个点直接访问str
数据
您希望对象的数据是可变的-wait\u\u输出是可变的-但是您不能对从str
继承的对象部分进行突变,这才是重要的数据。您试图做的是不可能的
使用字符串的C代码访问由str
类管理的实际字符串数据,而不是您正在编写的方法。它不关心您是否将另一个字符串作为属性附加到对象,或者您是否覆盖了一组方法。它比您的对象更接近str.\uuuuuuwhater.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu(您的对象)
,尽管它
在本例中,相关的C代码是os.stat
调用os.path.isdir
委托给的,但是几乎任何使用字符串的东西都将使用用C编写的东西,在某个点直接访问str
数据
您希望对象的数据是可变的——wait___\u输出是可变的,但您不能对从str
继承的对象部分进行突变,这才是重要的数据。
考虑os.path.isdir
的源代码。当您传入obj
时,可能会触发该值错误,因为您要计算的字符串是字符串子类的属性,而不是该子类应该表示的字符串。您必须在str
的源代码中多做一些工作,以找到要覆盖的正确成员
编辑:一种可能的解决方法是动态使用\uuuu init\uuu
。也就是说,获取在\uuuuu new\uuuuu
中呈现路径字符串所需的所有操作,并在该方法中返回类之前,将output\u str
设置为属性。现在,在您的\uuuu init\uuuu
中,调用super()。\uuuu init\uuuuu
,将self.output\u str
作为唯一参数。
考虑os.path.isdir
的源代码。当您传入obj
时,可能会触发该值错误,因为您要计算的字符串是字符串子类的属性,而不是该子类应该表示的字符串。您必须在str
的源代码中多做一些工作,以找到要覆盖的正确成员
编辑:一种可能的解决方法是动态使用\uuuu init\uuu
。也就是说,获取在\uuuuu new\uuuuu
中呈现路径字符串所需的所有操作,并在该方法中返回类之前,将output\u str
设置为属性。现在,在您的\uuuu init\uuuu
中,调用super()。\uuuu init\uuuu
,将self.output\u str
作为唯一参数。尝试os.path.isdir(str(obj))
,看看它是否正确works@Luka谢谢我知道它有效,但我不能。我不允许在课外更改代码。我需要构建一个与str完全兼容的类…如果您使用PathLike,在\uuuufspath\uuuuuuuu
中,您可以返回str(self.\u output\u str)
,否?自从>>打印(type(obj.\u output\u str)),它不会改变任何东西
尝试os.path.isdir(str(obj))
,看看它是否works@Luka谢谢我知道它有效,但我不能。我不允许在课外更改代码。我需要构建一个与str完全兼容的类…如果您使用PathLike,在\uuuufspath\uuuuuuuu
中,您可以返回str(self.\u output\u str)
,否?自从>>打印(type(obj.\u output\u str)),它不会改变任何东西你说的C代码处理字符串是什么意思
>>> print(os.path.isdir(obj))
... False **<<-- This one puzzles me**
print(os.path.isdir("/Users"))
... True
class ShellWrap(str,PathLike):
....
def __fspath__(self):
return self._output_str