1
class SoftDeleteMixin(object):
    deleted_at = Column(DateTime)
    deleted = Column(types.SoftDeleteInteger, default=0)

    def soft_delete(self, session):
        """Mark this object as deleted."""
        self.deleted = self.id
        self.deleted_at = timeutils.utcnow()
        self.save(session=session)

In class SoftDeleteMixin method soft_delete, it references nonexistent self.id and self.save. Why can it do that in python?

Note: the focus is the class can reference nonexistent variable and method, not that it is a Mixin class.

PZY
  • 131
  • 1
  • 16
  • 2
    Did you try to actually run your code and call `soft_delete`? You'll get an `AttributeError`. – Valentino Dec 25 '20 at 01:41
  • 4
    It can, and if you instantiate an object of this class and try to use that method, and it will throw an `AttributeError`. Note, the class seems to be intended to be used as a mixin, so whatever inherits from it likely is supposed to have those attributes – juanpa.arrivillaga Dec 25 '20 at 01:42
  • 1
    @Valentino In my code, I will inherit this class SoftDeleteMixin, and other class that includes id attribute and method soft_delete in my class. It work rightly. But i can't understand it. – PZY Dec 25 '20 at 01:52
  • @juanpa.arrivillaga Yes ,it is as a mixin. I also inherit other classes that have id attribute and method soft_delete. But if this, parent class use subclass attribute. Is it OK in python? – PZY Dec 25 '20 at 02:01
  • 2
    Have you *tried* it? `self` is just a reference to an instance, the instance that the method is being called on. Does that instance have an `id`? a `.save`? If it doesn't, it will throw an `AttributeError`, if it does, it will not. – juanpa.arrivillaga Dec 25 '20 at 02:02
  • Note, in Python, instance attributes don't really "belong" to any class. But even class attributes, which do belong to a particular class in a sense, can be used in any instance that inherits from that class... – juanpa.arrivillaga Dec 25 '20 at 02:04
  • Oh, i understand wrongly. I think **self** in python is the same as **this** in java before. – PZY Dec 25 '20 at 02:06
  • @PZY well, it is the same as in Java, but you are right, Java wouldn't allow something exactly like this. – juanpa.arrivillaga Dec 25 '20 at 02:16
  • @juanpa.arrivillaga It's different. In your java code, Bar class extends Foo class, so Bar class(child class) can use the public attribute from Foo class(parent class). But in my case, it seems that parents class uses the attribute from child class. – PZY Dec 25 '20 at 02:17
  • @PZY yes, I edited that. – juanpa.arrivillaga Dec 25 '20 at 02:19
  • 1
    "I think self in python is the same as this in java before." This is correct. `self` in Python is the same as `this` in Java. The issue at hand here is that inheritance in Python is very, very, very, very different than inheritance in Java. – Code-Apprentice Dec 25 '20 at 02:30
  • @Code-Apprentice But **this** can't reference child class attribute in Java. – PZY Dec 25 '20 at 02:35
  • @PZY That has nothing to do with `this` per se, but with the rules of inheritance in Java. As I said, inheritance is different in Python than it is in Java. – Code-Apprentice Dec 25 '20 at 16:27

2 Answers2

2

If you instantiate a SoftDeleteMixin class and call the soft_delete method, you'll get an AttributeError.

If as you said in the comment those attributes are instantiated somewhere else, even in a child class, and you call soft_delete on a child class instance, it works because the attribute is there at the time the method is called.

To explain it in a simple way, python is an interpreted language, and except for syntax it does not perform too much checks on the whole file when executing the code, until that actual line is actually executed.

So yes, you could think it's a bad design but it is not, it's an accepted practice (see this question for more details) and it is allowed by the laguage. You can define methods which reference attributes not defined in a __init__ method or as class attributes or whatever. The important thing is that the istance has the attribute when the method is executed. It does not matter where or when the attribute is actually defined.

Valentino
  • 7,291
  • 6
  • 18
  • 34
1

The word "mixin" in the class name means that this class is intended to be inherited by a class that already declares id and save(). If you try to use it by itself, it will cause errors.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268