如何在Python中对str进行子类化
我正在尝试对str对象进行子类化,并向其添加两个方法。我的主要目的是学习如何做。我陷入困境的地方是,我应该在一个元类中对string进行子类化,然后用那个元类创建我的类,还是直接用子类str创建我的类 另外,我想我需要以某种方式实现如何在Python中对str进行子类化,python,subclassing,fluent-interface,Python,Subclassing,Fluent Interface,我正在尝试对str对象进行子类化,并向其添加两个方法。我的主要目的是学习如何做。我陷入困境的地方是,我应该在一个元类中对string进行子类化,然后用那个元类创建我的类,还是直接用子类str创建我的类 另外,我想我需要以某种方式实现\uuuuuu new\uuuuu(),因为我的自定义方法将修改我的string对象,并返回新的mystr obj 我的类的方法应该可以与str方法完全链接,并且当自定义方法修改它时,应该始终返回一个新的我的类实例。我希望能够做到以下几点: a = mystr("so
\uuuuuu new\uuuuu()
,因为我的自定义方法将修改我的string对象,并返回新的mystr obj
我的类的方法应该可以与str方法完全链接,并且当自定义方法修改它时,应该始终返回一个新的我的类实例。我希望能够做到以下几点:
a = mystr("something")
b = a.lower().mycustommethod().myothercustommethod().capitalize()
issubclass(b,mystr) # True
a = mystr("something")
b = a.lower().mycustommethod().myothercustommethod().capitalize()
issubclass(b,mystr) # True
我想拥有str
拥有的所有能力。例如,a=mystr(“某物”)
然后我想像这样使用它,
a、 大写().mycustommethod().lower()
我的理解是,我需要实现\uuuu new\uuuu()
。我这样认为是因为strings方法可能会尝试创建新的str实例。因此,如果我覆盖\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。但是,在这种情况下,我不知道如何将参数传递给自定义类的\uuu init\uu()
方法。我想我需要使用type()
在\uuuuuuuuuuuuuuuuuuuu()
方法中创建一个新实例,对吗?如果您想在构造时修改字符串,覆盖\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
class caps(str):
def __new__(cls, content):
return str.__new__(cls, content.upper())
但是,如果您只想添加新方法,您甚至不必接触构造函数:
class text(str):
def duplicate(self):
return text(self + self)
请注意,继承的方法,例如upper()
仍将返回正常的str
,而不是text
,您可以尝试以下操作:
class mystr(str):
def new_method(self):
pass
但是您不能确定标准方法是否也会返回“mystr”实例,这里有一个快速的方法可以实现您的目的:基本上拦截每个函数调用,如果您看到它返回字符串,您可以将其转换回您自己的类类型
虽然这在这个简单的示例中有效,但它有一些局限性。除此之外,诸如下标运算符之类的运算符显然没有得到处理
class FunWrapper(object):
def __init__(self, attr):
self.attr = attr
def __call__(self, *params, **args):
ret = self.attr(*params, **args)
if type(ret) is str:
return Foo(ret)
return ret
class Foo(object):
def __init__(self, string):
self.string = string
def __getattr__(self, attr):
return FunWrapper(getattr(self.string, attr))
def newMethod(self):
return "*%s*" % self.string.upper()
f = Foo('hello')
print f.upper().newMethod().lower()
我正在尝试对str对象进行子类化,并向其添加两个方法。我的主要目的是学习如何做。
UserString
是在可以直接对str
进行子类化之前创建的,因此更倾向于将str
子类化,而不是使用UserString
(另一个答案建议)
当对不可变对象进行子类化时,通常需要在实例化对象之前修改数据——因此,您需要实现\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
,并调用父对象\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
在Python 3中,像这样调用super
更有效:
a = mystr("something")
b = a.lower().mycustommethod().myothercustommethod().capitalize()
issubclass(b,mystr) # True
a = mystr("something")
b = a.lower().mycustommethod().myothercustommethod().capitalize()
issubclass(b,mystr) # True
class Caps(str):
定义新内容(cls,内容):
返回super()
\uuuu new\uuuu
看起来像一个类方法,但实际上它是作为一个静态方法实现的,因此我们需要冗余地传递cls
作为第一个参数。然而,我们不需要@staticmethod
装饰器
如果我们像这样使用super
来支持Python 2,我们将更清楚地注意到冗余的cls
:
class Caps(str):
定义新内容(cls,内容):
返回super(Caps,cls)。\uuuu new\uuuu(cls,content.upper())
用法:
>Caps('foo')
“福”
>>>iInstance(大写('foo'),大写)
真的
>>>isinstance(大写('foo'),str)
真的
完整答案
到目前为止,没有一个答案符合您的要求:
我的类的方法应该可以完全链接到str方法,
并且在自定义方法时应始终返回一个新的my class实例
修改了它。我希望能够做到以下几点:
a = mystr("something")
b = a.lower().mycustommethod().myothercustommethod().capitalize()
issubclass(b,mystr) # True
a = mystr("something")
b = a.lower().mycustommethod().myothercustommethod().capitalize()
issubclass(b,mystr) # True
(我相信你的意思是isinstance()
,而不是issubclass()
)
您需要一种截取字符串方法的方法<代码>\uuuu getattribute\uuuuu
不执行此操作
现在:
>>> a = Caps("something")
>>> a.lower()
Caps('SOMETHING')
>>> a.casefold()
Caps('SOMETHING')
>>> a.swapcase()
Caps('SOMETHING')
>>> a.index('T')
4
>>> a.strip().split('E')
[Caps('SOM'), Caps('THING')]
本案所要求的工作:
>>> a.lower().mycustommethod().myothercustommethod().capitalize()
Caps('SOMETHING!!!')
对评论的回应
为什么Python3的唯一调用,即super().method(arg)性能更好
该函数已经可以访问\uuuu class\uuu
和self
,而无需执行全局和本地查找:
课堂演示:
def foo(self):
打印(局部变量())
打印(类)
>>>Demo().foo()
{'self':,'uuuuuuuuuuu类:}
有关更多信息,请参阅。我对其他答案的复杂性感到震惊,python标准库也是如此。您可以使用来对字符串进行子类化,并且不会干扰代理str
的方法
只需将其子类化,并添加您的方法self.data
包含由对象表示的实际字符串,因此您甚至可以通过在内部重新分配self.data
来实现str-“mutating”方法
.@yasar11732:sth在下面指出,a.capitalize()
将返回一个标准的、未修改的str
,而不是您的自定义类,因此a.capitalize().mycustommethod()
将失败。编写两个函数并直接执行mycustommethod(a.capitalize()).lower()
,这是一种非常非常好的编码实践,因为这不会让其他阅读您代码的人感到困惑(顺便说一句,“其他人”包括“您,两年后”)。更通用的方法是基于uu init_uu(self,*args,**kwargs)+super()正在报告弃用警告:对象。\uuuu init\uuuu()不接受任何参数。因此,我认为uuu new_uuuu(cls,*args,**kwargs)是一种更好的方法。或也许这解释得更好:另请参见:six.moves UserString
“但是UserString不是str的子类,因此如果需要进行即时检查,这不是一个选项。回答不错+1。不是json可序列化的tho。另外,重写\u str\uuuuuuuuu()
也是值得一提的,因为作为值访问self