从 str 或 int 继承
为什么我在创建从 str(或从 int 继承)继承的类时遇到问题,
class C(str):
def __init__(self, a, b):
str.__init__(self,a)
self.b = b
C("a", "B")
TypeError: str() takes at most 1 argument (2 given)
如果我尝试使用 int
而不是 str
,也会发生同样的情况,但它适用于自定义类。我需要使用 __new__
而不是 __init__
?为什么?
Why I have problem creating a class inheriting from str (or also from int)
class C(str):
def __init__(self, a, b):
str.__init__(self,a)
self.b = b
C("a", "B")
TypeError: str() takes at most 1 argument (2 given)
the same happens if I try to use int
instead of str
, but it works with custom classes. I need to use __new__
instead of __init__
? why?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
由于
__init__
是在对象构造之后调用的,因此修改不可变类型的值就为时已晚。请注意,__new__
是一个类方法,因此我调用了第一个参数cls
参见此处了解更多信息
Since
__init__
is called after the object is constructed, it is too late to modify the value for immutable types. Note that__new__
is a classmethod, so I have called the first parametercls
See here for more information
继承内置类型很少值得。你必须处理几个问题,但你并没有真正获得太多好处。
使用组合几乎总是更好。您可以将
str
对象保留为属性,而不是继承str
。您可以使用
__getattr__
手动或自动推迟任何您想要在底层str
self.s
上使用的方法。话虽这么说,需要您自己的字符串类型应该会让您停下来。有许多类应该存储字符串作为其主要数据,但您通常希望使用
str
或unicode
(如果您表示文本,则为后者)作为一般表示字符串。 (一个常见的例外是,如果您需要使用 UI 工具包的字符串类型。)如果您想向字符串添加功能,请尝试是否可以使用对字符串进行操作的函数而不是 >用作字符串的新对象,这使您的代码更简单并且与其他人的程序更兼容。Inheriting built-in types is very seldom worth while. You have to deal with several issues and you don't really get much benefit.
It is almost always better to use composition. Instead of inheriting
str
, you would keep astr
object as an attribute.you can defer any methods you want to work on the underlying
str
self.s
manually or automatically using__getattr__
.That being said, needing your own string type is something that should give you pause. There are many classes that should store a string as their main data, but you generally want to use
str
orunicode
(the latter if you're representing text) for general representation of strings. (One common exception is if you have need to use a UI toolkit's string type.) If you want to add functionality to your strings, try if you can to use functions that operate on strings rather than new objects to serve as strings, which keeps your code simpler and more compatible with everyone else's programs.当您实例化一个类时,您传入的参数将传递给该类的 __new__(构造函数),然后传递给该类的 __init__(初始化程序)方法。因此,如果您继承的类对实例化期间可能提供的参数数量有限制,则必须保证其 __new__ 和 __init__ 都不会获得更多参数比他们期望得到的。这就是你遇到的问题。您可以使用
C("a", "B")
实例化您的类。解释器在C
中查找__new__
方法。C
没有它,因此 python 会查看它的基类str
。由于它有一个,因此该值与两个参数一起使用和提供。但是 str.__new__ 期望仅获得一个参数(除了作为第一个参数的类对象之外)。因此引发了 TypeError 。这就是为什么您必须在子类中扩展它,类似于使用__init__
所做的事情。但请记住,它必须返回类实例,并且它是一个静态方法(无论它是否使用 @staticmethod 装饰器定义),如果您使用超级
功能。When you instantiate a class, the arguments that you pass in, are passed to both the
__new__
(constructor) and then to the__init__
(initializer) methods of the class. So if you inherit from a class that has restrictions on number of arguments that may be supplied during instantiation, you must guarantee that neither its__new__
, nor its__init__
would get more arguments than they expect to get. So that is the problem that you have. You instantiate your class withC("a", "B")
. The interpreter looks for__new__
method inC
.C
doesn't have it, so python peeps into its base classstr
. And as it has one, that one is used and supplied with the both arguments. Butstr.__new__
expects to get only one argument (besides its class object as the first argument). SoTypeError
is raised. That is why you must extend it in your child class similarly to what you do with__init__
. But bear in mind that it must return class instance and that it is a static method (irrespective of whether it is defined with@staticmethod
decorator or not) that counts if you usesuper
function.如果是不可变类型,请使用 __new__ :
print 返回 hello 。
Python 字符串是不可变类型。调用函数
__new__
来创建对象C
的新实例。 python__new__
函数基本上存在于允许从不可变类型继承。Use
__new__
in case of immutable types:print returns
hello
.Python strings are immutable types. The function
__new__
is called to create a new instance of objectC
. The python__new__
function is basically exists to allow inheritance from immutable types.仔细阅读 this 后,这是对 str 进行子类化的另一次尝试。其他答案的变化是使用 super(TitleText, cls).__new__ 在正确的类中创建实例。无论何时使用它,它的行为似乎都像 str,但它允许我重写一个方法:
这可以让你正确地进行切片和下标。这是干啥用的?用于在管理索引页面中重命名 Django 应用程序。
After carefully reading this, here is another attempt at subclassing str. The change from other answers is creating the instance in the correct class using
super(TitleText, cls).__new__
. This one seems to behave like a str whenever it's used, but has allowed me to override a method:This lets you do slicing and subscripting correctly. What's this for? For renaming the Django application in the admin index page.
当我试图找到一种方法来在引用的字典被删除后删除临时文件时,我遇到了这个问题。
上下文是一个 Flask 会话:用户可以上传一些文件,但在有效提交将他/她的数据传输到最终目的地所需的整个工作流程之前放弃。在那之前,我将文件保存在临时目录中。假设用户放弃并关闭浏览器窗口,我不希望这些文件徘徊。
由于我将临时路径保留在 Flask 会话中——这只是一个最终会被删除(例如超时)的字典,因此我可以自定义一个
str
类来保存临时目录地址/路径,并且有其__del__
方法处理临时目录删除。就是这样:
在你的 python 解释器/应用程序中实例化它:
当你退出解释器时:
就这样了。
I hit this question when trying to figure out a way to remove a temporary file after the dictionary it was being referred to goes deleted.
The context is a Flask session: the user can upload some files but give up before effectively commit the whole workflow it has to go through to get his/her data into the final destination. Until then, I keep the files in a temporary directory. Let's say the user give up and closes the browser window, I don't want those files lingering around.
Since I keep the temporary path in a Flask session -- which is just a dictionary that eventually goes deleted (e.g, timeout), I can customize a
str
class to hold the temporary directory address/path, and have its__del__
method handling the temporary directory deletion.Here it goes:
Instantiate it in your python interpreter/app:
When you exit the interpreter:
There you go.