Python - why can I call a class method with an instance?
You can call it on an instance because @classmethod
is a decorator (it takes a function as an argument and returns a new function).
Here is some relavent information from the Python documentation
It can be called either on the class (such as C.f()) or on an instance
(such as C().f()). The instance is ignored except for its class. If a
class method is called for a derived class, the derived class object
is passed as the implied first argument.
There's also quite a good SO discussion on @classmethod
here.
Call instance method in class method in Python
It's because of how you're calling second
.
Say you have such a class:
class A:
def do_thing(self):
pass
The following are equivalent:
a = A()
a.do_thing()
A.do_thing(a)
In other words, when we call a method of an instance, it is the same as looking up a function attribute of the class object and calling it with that instance as the first argument.
Now, note that when you call second
, you pass cls
to it. That is the class object and not an instance, which means that you're doing something like A.do_thing
. Therefore, for it to know which instance you want to call third
on, you need to pass in self
.
ELI5: Why can you call class methods within class methods without explicitly stating the class itself? (Ruby/Rails)
Whenever you call a method, Ruby first checks to see if it's defined on self
. There is only one exception to this that I know of - if you have a local variable with the same name as the method, it will reference the local variable instead:
def num; 1; end
num = 2
num # => 2
Class methods are the same as instance methods in this regard.
It's easier to think of the cases where you can't omit the self:
When using a setter method e.g.
self.foo = "bar"
it's required because Ruby needs to know you're not trying to just set a local variable (asfoo = "bar"
would):class Test
attr_writer :foo
def initialize
self.foo = 1 # calls the setter method
foo = 2 # creates a local variable
end
endWhen there's ambiguity between a local variable and a method (both have the same name) and you want to call the method:
class Foo
def self.a; 1; end
def self.b
a = 2
a # references local variable
self.a # calls method
a() # can also call the method by writing out parens (removes ambiguity)
end
endWhen
self
is not what you want it to be in that scope.class Foo
def self; a; 1
end
a # obviously doesn't work, it isn't defined here
Foo.a # worksWhen the method name is the same as a reserved word (e.g.
class
)def class_name
class.name # syntax error, it thinks you want to define a class
self.class.name # works
end
Calling instance method from class method, allowed in python3, disallowed in python 2?
In Python 3 methods are regular function objects (not "unbound method" instances) and therefore they do not check that the first argument is an instance of the class.
Not sure why this change was considered important (uniformity or performance, probably) but what you observed looks like an unwanted side effect of this choice.
How to define one method as both instance method and class method (sharing the same name), each with different arguments?
You can let self
take a default argument as well, so that you can distinguish between mine.bar()
and MyClass.bar()
. The price is that the other two arguments must be keyword arguments.
class MyClass:
_sentinel = object()
def bar(self=None, *, arg1=_sentinel, arg2=_sentinel):
if self is not None:
if arg1 is _sentinel:
arg1 = self.arg1
if arg2 is _sentinel:
arg2 = self.arg2
else:
if arg1 is _sentinel:
raise ValueError("Missing required arg1")
if arg2 is _sentinel:
raise ValueError("Missing required arg2")
return foo(arg1, arg2)
mine.bar() # self is mine, arg1 is _sentinel, arg2 is _sentinel
MyClass.bar(arg1=3, arg2=4)
How to call instance method from within class method?
If you want to send an instance method, then you need an instance. There's no way around that.
If your class method wants to call an instance method, then it is quite possible that either the instance method should be a class method, or the class method should be an instance method. So have a look at that and maybe change your design.
Otherwise, your class method must create an instance, or get an instance from somewhere, and send the instance method to the instance.
instance methods from class methods swift
What you are trying to do rarely makes any sense from a design perspective.
By definition, an instance method
operates on an instance
of an object.
For example, it might require access to some instance members, or somehow meddle with the state of the object you call the method on.
class
methods on the other hand do not require an instance to be able to call them - and should in general only operate on the given parameters, not be dependant on shared state.
If you need to call instanceMethod()
in classMethod()
, and instanceMethod()
does not require any state - why is it not also a class
method, or a (global) pure function?
Related Topics
Ruby on Rails - Search in Database Based on a Query
How to Count Decimal Places in SQL
Execute Sp_Executesql for Select...Into #Table But Can't Select Out Temp Table Data
How to Pass Table Name as a Parameter in Oracle
Adding Constraints That Check a Separate (Linked) Table for a Value
How to Create Temp Table with Select * into Temptable from Cte Query
Postgresql Extract Last Row for Each Id
SQL Server Management Studio 2008 Runas User on Different Domain Over Vpn
No Unique or Exclusion Constraint Matching the on Conflict
How to Run SQL Statements on a Named Range Within an Excel Sheet
Why am I Able to Call the Class Method as If It Were an Instance Method Here
SQL Error: Ora-02291: Integrity Constraint
Do Conditional Insert with SQL
Fast Way to Generate Concatenated Strings in Oracle
Returning Result Even for Elements in In List That Don't Exist in Table
How to Find Out What Foreign Key Constraint References a Table in SQL Server