Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

309
Visualizações
Redefine Method of an Object

I've got a class, where a method should only run once. Of course, it could easily be done with artificial has_executed = True/False flag, but why use it, if you can just delete the method itself? python's a duck-typed language, everything is a reference, bla-bla-bla, what can go wrong?

At least it was the thought. I couldn't actually do it:

class A:    
    def b(self):
        print("empty")
        self.__delattr__('b')

a = A()
a.b()

raises AttributeError: b. However, executing self.__getattribute__('b') returns <bound method A.b of <__main__.A object at 0x000001CDC6742FD0>>, which sounds stupid to me: why is a method any different from an attribute, since everything in python is just a reference to an object? And why can I __getattribute__, but not __delattr__?

The same goes to redefinition. I can easily set any attribute, but methods are a no-no?

class A:
    def b(self):
        print("first")
        self.__setattr__('b', lambda self: print(f"second"))

a = A()
a.b()
a.b()

results into TypeError: <lambda>() missing 1 required positional argument: 'self'. Which, of course, means, that now python isn't using dot-notation as intended. Of course, we could ditch the self attribute in the lambda altogether, considering we've got the reference to it already in b. But isn't it incorrect by design?

The further I'm trying to take python to the limit, the more frustrated I become. Some imposed limitations (or seemingly imposed?) seem so unnatural, considering the way the language is marketed. Shouldn't it allow this? Why doesn't it work?

UPD

Ok, consider this:

class A:
    def __init__(self):
        self.variable = 1

    def b(self):
        print("old")
        self.variable += 1
        def new_b():
            print("new")
            self.variable += 15
        self.__setattr__('b', new_b)

It will work and do what we want: none of other objects will have their A.b method redefined once one object kind of overlays its b definition. (overlays, since everyone so far says that you cannot redefine a method for an object, but instead only kind of hide it from the caller behind another attribute with the same name, as far as I understand).

Is this good?

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

It doesn't work because b isn't an attribute belonging to the instance, it belongs to the class. So you can't delete it on the instance because it isn't there to be deleted.

>>> a = A()
>>> list(a.__dict__)
[]
>>> list(A.__dict__)
['__module__', 'b', '__dict__', '__weakref__', '__doc__']

When a.b is evaluated, Python will see that a has no instance attribute named b and fall back to the class. (It's a little more complicated because when falling back to the class, it will not simply return the method itself, but a version of the method which is bound to the instance a.)

Since you don't want to delete the method on the class, the way to go is to replace the method on the instance. I don't know why you tried to do this with __setattr__ - there is no need for that, simply assign self.b = ... as normal. The reason your attempt failed is because your lambda requires a positional parameter named self, but this parameter will not be automatically bound to the instance when you look it up, because it is an instance attribute, not a class attribute.

class A:
    def b(self):
        print('first')
        self.b = lambda: print('second')

Usage:

>>> a = A()
>>> a.b()
first
>>> a.b()
second
over 4 years ago · Santiago Trujillo Relatório

0

Well in python you have 2 types of attributes

  • A class attribute is a variable that belongs to a certain class, and not a particular object. Every instance of this class shares the same variable. These attributes are usually defined outside the init constructor
  • An instance/object attribute is a variable that belongs to one (and only one) object. Every instance of a class points to its own attributes variables. These attributes are defined within the init constructor.

In case of a class attribute its part of the class descriptor, so you cannot delete it from the object attributes like self.__deleteattr__ or add new one with __setattr__ as it alters the class descriptor and reflects on all objects. Such an operation can have devastating effects.

Its very similar to a class variable as well. You can however change the behavior with overriding or reassigning like below

class A:    
    def b(self):
        print("empty")
        A.b =  lambda self: print(f"second")

a = A()
a.b()
a.b()
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda