3

In Python, is it possible to add new methods to built-in classes, such as Tuple. I'd like to add 2 new methods: first() returns the first element of a tuple, and second() returns a new tuple without the first element.

So for example:

x = (1, 2, 3)

x.first()   # 1
x.second()  # (2, 3)

Thanks

user1797036
  • 71
  • 1
  • 4
  • 4
    No, you must create your own class. (You can subclass tuple.) – BrenBarn Sep 21 '13 at 18:11
  • 1
    Why don't you just slice the tuple? first is `t[0]` and "second" is `t[1:]`. – Burhan Khalid Sep 21 '13 at 18:17
  • So python classes are closed and cannot be extended like in Ruby or C#. Is that correct? I'm new to python, so just want to know what can and can't be done. Being able to extend existing classes without altering their default behaviors can be very useful. An example is LINQ was mostly implemented with extension methods. – user1797036 Sep 21 '13 at 18:54
  • @user1797036 No. Classes implemented in C (which is true of most builtin classes) cannot be monkeypatched. However, they can be extended by inheritance. – Marcin Sep 21 '13 at 19:37

2 Answers2

5

Yes, but don't.

There exists a dark and dangerous forbiddenfruit that unsafely and dangerously allows such a thing. But it's a dark place to go.

Rather, you can make a new class:

class MyTuple(tuple):
    def first(self):
        return self[0]

    def second(self):
        return self[1:]

mt = MyTuple((1, 2, 3, 4))

mt.first()
#>>> 1
mt.second()
#>>> (2, 3, 4)

Preferably you can create an actual linked list that doesn't require copying every time you call this.

Preferably, don't do that either because there are almost no circumstances at all to want a self-implemented or singly-linked-list in Python.

Veedrac
  • 58,273
  • 15
  • 112
  • 169
  • This is the same as my answer, and BrenBarn's comment, only later, and with less explanation. – Marcin Sep 21 '13 at 18:19
  • Python has a standard linked datastructure: `deque` – Marcin Sep 21 '13 at 18:20
  • You don't cover actually modifying the built-in class, though, which I thought was a relevant (if not useful) addition. – Veedrac Sep 21 '13 at 18:21
  • Neither do you. forbiddenfruit doesn't actually alter the class; it creates a wrapper, and alters the binding of the global name. – Marcin Sep 21 '13 at 18:23
  • "forbiddenfruit doesn't actually alter the class". I'm very dubious of that claim. – Veedrac Sep 21 '13 at 18:29
  • Which I did. What makes you think the builtin isn't modified? What do you think happens? Actually, I've thought of a way to test this. Wait a mo. // And I'm right. The `id` of `str` is the same before and after the patch, hence it is the same object. I wasn't snarky to you, please don't be to me. – Veedrac Sep 21 '13 at 18:31
  • What makes me think the builtin isn't modified is that there is no part of the code which modifies any builtin object. – Marcin Sep 21 '13 at 18:35
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/37794/discussion-between-veedrac-and-marcin) – Veedrac Sep 21 '13 at 18:36
  • Unless you add `__slots__` to your class its instances have a unnecessary `__dict__` instance. – Christian Heimes Sep 21 '13 at 18:52
3

No. You could use a namedtuple to introduce names for various positions; or you could subclass tuple; or you could simply write functions. There's nothing wrong with a function.

However, absolutely none of these are a good idea. The best idea is just to write code like everyone else: use subscripts and slices. These are entirely clear, and known to everyone.

Finally, your names are highly misleading: first returns the first element; second returns a tuple composed of the second and third elements.

Marcin
  • 48,559
  • 18
  • 128
  • 201