Python str 子类表示一个不是真正字符串的值

标签 python string class inheritance subclass

我是Python新手。致力于扩展旧模块。到目前为止,它有一个返回 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

令我困惑的是:

 >>> print(os.path.isdir(obj))
... False **<<-- This one puzzles me**
print(os.path.isdir("/Users"))
... True

我尝试添加 PathLike 继承并实现另一个 dunder,但没有成功:

class ShellWrap(str,PathLike):
   ....
   def __fspath__(self):
      return self._output_str

似乎还有一个dunder我未能实现。但哪个?

但是,我确实在调试器中看到了一些奇怪的东西。当我戴上 watch obj - 它说它是一个类 str但调试器显示的值不带引号(与其他“纯”字符串不同)。 手动向调试器中的字符串添加引号 - 使其可以工作,但我猜编辑字符串可能会创建一个新对象,这次是纯 str。

我错过了什么?

编辑:在意识到(参见已接受的答案)我尝试做的事情是不可能的之后,我决定挑战必须子类化 str 的决定。 。 所以现在我的类没有继承任何东西。它只是实现 __str__, __repr__ and __fspath__这似乎就足够了!显然只要str继承就在那里——它获得优先权,dunders不会被调用,它会欺骗一些库去获取str值的底层C存储

最佳答案

enter image description here

考虑os.path.isdir的来源。当您传入 obj 时,您可能会触发该值错误,因为您要评估的字符串是字符串子类的属性,而不是子类应该表示的字符串。您必须在 str 的源代码中多花点功夫才能找到要覆盖的正确成员。

编辑:解决此问题的一种可能方法是动态使用 __init__ 。也就是说,在__new__中完成渲染路径字符串所需的一切,并在该方法中返回类之前,将output_str设置为一个属性。现在,在您的 __init__ 中,以 self.output_str 作为唯一参数调用 super().__init__

关于Python str 子类表示一个不是真正字符串的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61860526/

相关文章:

python - 同时显示多个vtk渲染窗口

C++ 实例创建顺序有何影响?

python - 有没有办法连接 "list display"中的 2 个模型字段名称以在 Django Admin 中显示为一列?

python - 在 Visual Studio Code 中从正确的 anaconda 环境启动 PyLint

java - 如何对字符串应用掩码?

javascript - 上标 .toFixed() 的结果

javascript - Javascript 中的类继承

java - 类图和管理员权限

python - Tensorflow:对文本数据进行分类

c - sscanf 忽略 C 中的空格