0

I have a class, and would like to change an object of it (similar to the pop method of lists), without adding an foo = foo.bar()

In simpler terms, i'd like to do foo.bar() instead of foo = foo.bar(). Is this possible in python? Here's some code that i have, which hopefully furthers understanding:

class mystr(str):
    def pop(self, num):
        self = list(self)
        changed = self.pop(num)  # The particular character that was removed
        self = ''.join(self)  # The rest of the string
    
        # Somewhere in here i need to be able to change the actual variable that pop() was called on

        return changed  # Emulates python lists' way of returning the removed element.


my_var = mystr("Hello World!")
print(my_var.pop(4)  # Prints 'o', as you would expect
print(my_var)  # But this still prints 'Hello World!', instead of 'Hell World!'
# It isn't modified, which is what i want it to do

1
  • Assignment to self inside a method doesn't actually change what the instance is. Strings are immutable, which is why they don't have a pop method to start with. Commented Nov 22, 2020 at 8:20

2 Answers 2

2

You can, but not with str.


What you're looking for is a way to mutate your object. For most classes you write yourself, doing that is straightforward:

class Foo:
    def __init__(self):
        self.stuff = 0
    def example(self):
        self.stuff += 1

Here, calling example on a Foo instance mutates it, by changing its stuff instance attribute.


str, however, is immutable. It stores its data in C-level data structures and provides no mutator methods, so there's no way to modify its data. Even if you used ctypes to bypass the protection, you'd just get a bunch of memory corruption bugs.

You can add your own attributes in a subclass, and those will be mutable, but if you do that to fake a mutable string, you might as well just not inherit from str. Inheriting from str in that case will only cause bugs, with some code looking at your "fake" data and other code looking at the "real" underlying str data.


Most likely, the way to go will be one of two options. The first is to just use regular strings without your subclass or the methods you want to add. The second is to write a class that doesn't inherit from str.

Sign up to request clarification or add additional context in comments.

1 Comment

Hm, sounds like a fun project to make my own str class and add all the things it has currently. I'm going to attempt to do this, if i succeed or not i'll post a github link :)
0

You could achieve that by encapsulating a string, rather then inheriting from it:

class mystr:
    def __init__(self, string):
        self._str = string

    def pop(self, num):
        string_list = list(self._str)
        changed = string_list.pop(num)  # The particular character that was removed
        self._str = ''.join(string_list)  # The rest of the string

        return changed  # Emulates python lists' way of returning the removed element.

    def __repr__(self):
        return self._str

Running the same code with this class instead will print:

o
Hell World!

4 Comments

That works wonderfully, i'm going to remake the entire string object in python, so i'll add this to the code once i'm done
That's a misleading __repr__ - at most, something like that should be __str__. If you've got a mystr object x and you type x at an interactive prompt after you've forgotten what you stored there, something like mystr('Hello World!') is going to be a lot more helpful than just seeing Hello World!, and something like mystr('[1, 2, 3]') is going to be a lot more helpful than [1, 2, 3] if you have a mystr instance wrapping a string that looks like a list.
@user2357112supportsMonica I'll take this into mind, and make it display something like mutablestr("Hello World!") instead of Hello World!. Thanks for the suggestion!
@user2357112supportsMonica A very good point indeed! I didn't think on that and just implemented __repr__ on the thought that __str__ takes it if it's not implemented and on the grounds that I'm lazy... ^_^

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.