Why does assigning to self not work, and how to work around the issue?

天大地大妈咪最大 提交于 2019-11-27 08:02:20

问题


I have a class (list of dicts) and I want it to sort itself:

class Table(list):
…
  def sort (self, in_col_name):
    self = Table(sorted(self, key=lambda x: x[in_col_name]))

but it doesn't work at all. Why? How to avoid it? Except for sorting it externally, like:

new_table = Table(sorted(old_table, key=lambda x: x['col_name'])

Isn't it possible to manipulate the object itself? It's more meaningful to have:

class Table(list):
  pass

than:

class Table(object):
  l = []
  …
  def sort (self, in_col_name):
    self.l = sorted(self.l, key=lambda x: x[in_col_name])

which, I think, works. And in general, isn't there any way in Python which an object is able to change itself (not only an instance variable)?


回答1:


You can't re-assign to self from within a method and expect it to change external references to the object.

self is just an argument that is passed to your function. It's a name that points to the instance the method was called on. "Assigning to self" is equivalent to:

def fn(a):
   a = 2
a = 1
fn(a)
# a is still equal to 1

Assigning to self changes what the self name points to (from one Table instance to a new Table instance here). But that's it. It just changes the name (in the scope of your method), and does affect not the underlying object, nor other names (references) that point to it.


Just sort in place using list.sort:

def sort(self, in_col_name):
    super(Table, self).sort(key=lambda x: x[in_col_name])



回答2:


Python is pass by value, always. This means that assigning to a parameter will never have an effect on the outside of the function. self is just the name you chose for one of the parameters.




回答3:


I was intrigued by this question because I had never thought about this. I looked for the list.sort code, to see how it's done there, but apparently it's in C. I think I see where you're getting at; what if there is no super method to invoke? Then you can do something like this:

class Table(list):
    def pop_n(self, n):
        for _ in range(n):
            self.pop()

>>> a = Table(range(10))
>>> a.pop_n(3)
>>> print a
[0, 1, 2, 3, 4, 5, 6]

You can call self's methods, do index assignments to self and whatever else is implemented in its class (or that you implement yourself).



来源:https://stackoverflow.com/questions/18600382/why-does-assigning-to-self-not-work-and-how-to-work-around-the-issue

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!