开发者

How do I add my own custom attributes to existing built-in Python types? Like a string? [duplicate]

This question already has answers here: Can I add custom methods/attributes to built-in Python types? (8 answers) Closed 7 ye开发者_如何学编程ars ago.

I want to do something like this...

def helloWorld():
  print "Hello world!"
str.helloWorld = helloWorld
"foo".helloWorld()

Which would print out "Hello world!"

EDIT: Refer to Can I add custom methods/attributes to built-in Python types?


On CPython you can use ctypes to access the C-API of the interpreter, this way you can change builtin types at runtime.

import ctypes as c


class PyObject_HEAD(c.Structure):
    _fields_ = [
        ('HEAD', c.c_ubyte * (object.__basicsize__ -
                              c.sizeof(c.c_void_p))),
        ('ob_type', c.c_void_p)
    ]

_get_dict = c.pythonapi._PyObject_GetDictPtr
_get_dict.restype = c.POINTER(c.py_object)
_get_dict.argtypes = [c.py_object]

def get_dict(object):
    return _get_dict(object).contents.value

def my_method(self):
    print 'tada'
get_dict(str)['my_method'] = my_method

print ''.my_method()

Although this is interesting to look at and may be quite interesting to figure out... don't ever use it in productive code. Just subclass the builtin type or try to figure out if there is another, may be more pythonic, approach to your problem.


In short, you can't. The Python Way would be to subclass String and work from there.


Here's an idea. It isn't perfect, because it doesn't work for all strings, but it might be helpful.

To set attributes of a string or any other object:

def attr(e,n,v): #will work for any object you feed it, but only that object
    class tmp(type(e)):
        def attr(self,n,v):
            setattr(self,n,v)
            return self
    return tmp(e).attr(n,v)

Here's an example:

>>> def helloWorld():
...     print("hello world!") #python 3
...
>>> a=attr("foo",'heloWorld',helloWorld)
>>> a
'foo'
>>> a.helloWorld()
hello world!
>>> "foo".helloWorld()
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    "foo".helloWorld()
AttributeError: 'str' object has no attribute 'helloWorld'


Ruby way:

"1".to_i
"1".to_roman 

Python way:

int("1")
Roman("1") # or 
Roman.fromstring("1") 

Where Roman will work on a fixed list of built-in types or anything with a __int__ method.

It is an implementation limitation of CPython that you can't set attributes of built-in/extension types. It is accompanied by cultural preference to avoid monkey-patching in favor of stand-alone functions, custom classes that have as an attribute desired object (or even subclassing in rare cases).


To do that you can subclass str.

However, while technically possible, most of the time you are subclassing builtins (such as str) you are looking at a 'has-a' kind of relationship, not 'is-a', therefore composition should be used, not inheritance (meaning you should create a class with a string as an instance attribute, rather than subclass string).


You don't. Use separate dictionaries to "attach" (logically speaking) information to immutable values like strings or numbers (the string or number value as key, the information as corresponding value in the dict).


Python does not support that feature.


You can't, it isn't Pythonic. Monkey-patching isn't a commonly used feature of Python, so for performance -- I believe -- reasons you can't do it on the built it classes or instances thereof.

In fact, it has its own name in Python: duck-punching.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜