In Python, change the behavior of the method depending on how it is called

Results of normal definitions and calls

There are three types of methods in Python classes.

--Normal method (instance method) --The first argument is mandatory and is customarily set to self. --When called via an instance, the called instance is included in the first argument. --When called via a class, the arguments at the time of calling are passed as they are. --Class method --Define with @classmethod. The first argument is mandatory and is customarily set to cls. --When called via an instance, the class of the called instance is included in the first argument. --When called via a class, that class is included in the first argument. --Static method --Define with @staticmethod. The argument is not required. --The argument when called is passed as it is.

class C:
  val = 20
  def __init__(self):
    self.val = 1
  def normal_method(self, v):
    return self.val + v + 2
  @classmethod
  def class_method(cls, v):
    return cls.val + v + 3
  @staticmethod
  def static_method(v):
    return C.val + v + 4

i = C()
i.normal_method(5)    # i.val + 5 + 2 = 1 + 5 + 2 = 8
i.class_method(6)     # C.val + 6 + 3 = 20 + 6 + 3 = 29
i.static_method(7)    # C.val + 7 + 4 = 20 + 7 + 4 = 31
C.normal_method(5)    # requires 2 args but 1: error
C.normal_method(i, 6) # i.val + 6 + 2 = 1 + 6 + 2 = 9
C.normal_method(C, 7) # C.val + 7 + 2 = 20 + 7 + 2 = 29
C.class_method(8)     # C.val + 8 + 3 = 20 + 8 + 3 = 31
C.static_method(9)    # C.val + 9 + 4 = 20 + 9 + 4 = 33

Change the behavior depending on how the method is called

Normal methods are still functions.

--The first argument is self, which is just a promise, and there are no restrictions on the type of self. --When you call it via an instance, the processing system automatically puts that instance in the first argument.

Taking this as a counter-product, the behavior can be changed by the first argument.

class C:
  #Added to the above
  def trick_method(arg, v):
    if isinstance(arg, C):
      return arg.val * 2 * v
    else:
      return C.val + arg * v

i.trick_method(4)    # i.val * 2 * 4 = 1 * 2 * 4 = 8
C.trick_method(5)    # requires 2 args but 1: error
C.trick_method(6, 7) # C.val + 6 * 7 = 20 + 6 * 7 = 62
C.trick_method(i, 8) # i.val * 2 * 8 = 1 * 2 * 8 = 16
C.trick_method(C, 9) # C.val + C * v: error

The above trick_method () behaves like a normal method via an instance and like a static method via a class.

Normally, if the behavior is different, it should be a different method.

Illustration

I came up with such a strange usage while creating a class that manages instances as a group.

class Student:
  rooms = {}
  def __init__(self, room):
    self.myroom = room
    if not room in Student.rooms:
      Student.rooms [room] = []
    Student.rooms [room].append(self)

  def classmates(self_or_room):
    if isinstance(self_or_room, Student):
      self = self_or_room
      for s in Student.rooms[self.myroom]:
        if s != self:
          yield s
    elif self_or_room in Student.rooms:
      room = self_or_room
      return iter(Student.rooms[room])

Ann = Student('3-A')
Bob = Student('3-B')
Cathy = Student('3-B')
Dan = Student('3-A')
Ellen = Student('3-A')
Fred = Student('3-B')

mates_of_ann = Ann.classmates() # Dan, Ellen
mates_of_3A = Student.classmates('3-A') # Ann, Dan, Ellen

mates_of_bob = Bob.classmates() # Cathy, Fred
mates_of_3B = Student.classmates('3-B') # Bob, Cathy, Fred

Caution

This method cannot be used with methods with decorators (such as @ property or @ classmethod).

Recommended Posts

In Python, change the behavior of the method depending on how it is called
Find out the name of the method that called it from the method that is python
Differences in sys.path depending on how Python is started (v3.8.2)
How is the progress? Let's get on with the boom ?? in Python
Check the behavior of destructor in Python
The return value of len or unichr may change depending on whether it is UCS-2 or UCS-4.
About the behavior of Model.get_or_create () of peewee in Python
How the reference of the python array changes depending on the presence or absence of subscripts
How to get the number of digits in Python
Difference in results depending on the argument of multiprocess.Process
rsync Behavior changes depending on the presence or absence of the slash in the copy source
How to check in Python if one of the elements of a list is in another list
How strong is your Qiita? Statistics on the number of Contributes seen in the data
A note on the default behavior of collate_fn in PyTorch
Test.py is not reflected on the web server in Python3.
The AWS IP range is different depending on the acquisition method.
The story of how the Python bottle worked on Sakura Internet
How to use the __call__ method in a Python class
Change the Python version of Homebrew
How to determine the existence of a selenium element in Python
How to change the log level of Azure SDK for Python
Unfortunately there is no sense of unity in the where method
How to know the internal structure of an object in Python
How to change the color of just the button pressed in Tkinter
How easy is it to synthesize a drug on the market?
How to check the memory size of a variable in Python
Delete a particular character in Python if it is the last
How to judge that the cross key is input in Python3
Feel free to change the label of the legend in Seaborn in python
How to use the asterisk (*) in Python. Maybe this is all? ..
How to check the memory size of a dictionary in Python
A function that measures the processing time of a method in python
How to update the python version of Cloud Shell on GCP
I did a lot of research on how Python is executed
Get the number of readers of a treatise on Mendeley in Python
A simple reason why the return value of round (2.675,2) is 2.67 in python (it should be 2.68 in reality ...)
Change the length of Python csv strings
Behavior change of [Diagram / Timeline] in Choregraphe 2.5.5.5
Change the saturation and brightness of color specifications like # ff000 in python 2.5
Let's change the color scheme of iTerm2 automatically depending on the time zone
The result of installing python in Anaconda
[Java] [Linux] Investigating how the implementation of Java child processes on Linux is realized
What is "mahjong" in the Python library? ??
[python] [meta] Is the type of python a type?
The basics of running NoxPlayer in Python
What kind of book is the best-selling "Python Crash Course" in the world?
Change the order of PostgreSQL on Heroku
In search of the fastest FizzBuzz in Python
[Introduction to Python] What is the method of repeating with the continue statement?
How to use is and == in Python
How to input a character string in Python and output it as it is or in the opposite direction.
An engineer who has noticed the emo of cryptography is trying to implement it in Python and defeat it
How to pass the execution result of a shell command in a list in Python
[Linux] Difference in time information depending on the clock ID of the clock_gettime () function
I want to use Python in the environment of pyenv + pipenv on Windows 10
If branch depending on whether there is a specific element in the list
I was in trouble because the behavior of docker container did not change
Let's automatically display the lyrics of the song being played on iTunes in Python
[Python] How to name table data and output it in csv (to_csv method)
Set an upper limit on the number of recursive function iterations in Python
Differences in the behavior of each LL language when the list index is skipped