Inner class function without self
Peace, everyone!
I'm using Python 3.6.3 and I find strange that such construction is possible:
class TestClass(object):
def __init__(self):
self.arg = "arg"
def test():
print("Hey test")
And using:
>>> TestClass.test()
"Hey test"
I know that in Python there are standard methods with self
as parameter (don't know how to call them properly), static methods, class methods, abstract methods.
But what kind of method the test()
is?
Is it static method?
Edited:
Are there any useful usecases of such method of determining a function inside a class?
python python-3.x class
|
show 1 more comment
Peace, everyone!
I'm using Python 3.6.3 and I find strange that such construction is possible:
class TestClass(object):
def __init__(self):
self.arg = "arg"
def test():
print("Hey test")
And using:
>>> TestClass.test()
"Hey test"
I know that in Python there are standard methods with self
as parameter (don't know how to call them properly), static methods, class methods, abstract methods.
But what kind of method the test()
is?
Is it static method?
Edited:
Are there any useful usecases of such method of determining a function inside a class?
python python-3.x class
2
why do you find that code strange?
– mast3rd3mon
Nov 1 '17 at 11:52
test
is a function taking no parameters and you're calling it without parameters. All good. Now,TestClass().test()
OTOH is a different story…
– deceze♦
Nov 1 '17 at 11:53
3
Yes. It is very weird that it changed "Hey" to lowercase.
– stark
Nov 1 '17 at 11:55
3
Is the ambiguity ofself.test
a part of the question, or just a coincidence?
– tobias_k
Nov 1 '17 at 12:00
@tobias_k sorry, it's just coincidence, i fix it
– Gusev Slava
Nov 1 '17 at 12:01
|
show 1 more comment
Peace, everyone!
I'm using Python 3.6.3 and I find strange that such construction is possible:
class TestClass(object):
def __init__(self):
self.arg = "arg"
def test():
print("Hey test")
And using:
>>> TestClass.test()
"Hey test"
I know that in Python there are standard methods with self
as parameter (don't know how to call them properly), static methods, class methods, abstract methods.
But what kind of method the test()
is?
Is it static method?
Edited:
Are there any useful usecases of such method of determining a function inside a class?
python python-3.x class
Peace, everyone!
I'm using Python 3.6.3 and I find strange that such construction is possible:
class TestClass(object):
def __init__(self):
self.arg = "arg"
def test():
print("Hey test")
And using:
>>> TestClass.test()
"Hey test"
I know that in Python there are standard methods with self
as parameter (don't know how to call them properly), static methods, class methods, abstract methods.
But what kind of method the test()
is?
Is it static method?
Edited:
Are there any useful usecases of such method of determining a function inside a class?
python python-3.x class
python python-3.x class
edited Nov 23 '18 at 7:08
thepurpleowl
99112
99112
asked Nov 1 '17 at 11:50
Gusev SlavaGusev Slava
779716
779716
2
why do you find that code strange?
– mast3rd3mon
Nov 1 '17 at 11:52
test
is a function taking no parameters and you're calling it without parameters. All good. Now,TestClass().test()
OTOH is a different story…
– deceze♦
Nov 1 '17 at 11:53
3
Yes. It is very weird that it changed "Hey" to lowercase.
– stark
Nov 1 '17 at 11:55
3
Is the ambiguity ofself.test
a part of the question, or just a coincidence?
– tobias_k
Nov 1 '17 at 12:00
@tobias_k sorry, it's just coincidence, i fix it
– Gusev Slava
Nov 1 '17 at 12:01
|
show 1 more comment
2
why do you find that code strange?
– mast3rd3mon
Nov 1 '17 at 11:52
test
is a function taking no parameters and you're calling it without parameters. All good. Now,TestClass().test()
OTOH is a different story…
– deceze♦
Nov 1 '17 at 11:53
3
Yes. It is very weird that it changed "Hey" to lowercase.
– stark
Nov 1 '17 at 11:55
3
Is the ambiguity ofself.test
a part of the question, or just a coincidence?
– tobias_k
Nov 1 '17 at 12:00
@tobias_k sorry, it's just coincidence, i fix it
– Gusev Slava
Nov 1 '17 at 12:01
2
2
why do you find that code strange?
– mast3rd3mon
Nov 1 '17 at 11:52
why do you find that code strange?
– mast3rd3mon
Nov 1 '17 at 11:52
test
is a function taking no parameters and you're calling it without parameters. All good. Now, TestClass().test()
OTOH is a different story…– deceze♦
Nov 1 '17 at 11:53
test
is a function taking no parameters and you're calling it without parameters. All good. Now, TestClass().test()
OTOH is a different story…– deceze♦
Nov 1 '17 at 11:53
3
3
Yes. It is very weird that it changed "Hey" to lowercase.
– stark
Nov 1 '17 at 11:55
Yes. It is very weird that it changed "Hey" to lowercase.
– stark
Nov 1 '17 at 11:55
3
3
Is the ambiguity of
self.test
a part of the question, or just a coincidence?– tobias_k
Nov 1 '17 at 12:00
Is the ambiguity of
self.test
a part of the question, or just a coincidence?– tobias_k
Nov 1 '17 at 12:00
@tobias_k sorry, it's just coincidence, i fix it
– Gusev Slava
Nov 1 '17 at 12:01
@tobias_k sorry, it's just coincidence, i fix it
– Gusev Slava
Nov 1 '17 at 12:01
|
show 1 more comment
5 Answers
5
active
oldest
votes
In Python 3, (unlike Python 2) a function accessed and called from the class is just another function; nothing special:
Note that the transformation from function object to instance method
object happens each time the attribute is retrieved from the instance.
[Emphasis mine]
You just happened to be calling the function with the right set of parameters albeit accessed via the class object. Same as calling the underlying function object for the method via an instance:
TestClass().test.__func__() # "Hey test"
A quick test explains it further:
print(TestClass().test is TestClass.test)
# False
print(TestClass().test.__func__ is TestClass.test)
# True
However, in Python 2, the behaviour is different as the transformation from function object to method object happens when the attribute is accessed via both the class or instance:
Note that the transformation from function object to (unbound or
bound) method object happens each time the attribute is retrieved from
the class or instance.
[Emphasis mine]
add a comment |
Let me explain with an example:
class TestClass(object):
def __init__(self):
self.arg = "arg"
def test1():
print("class method test1, Hey test")
@classmethod
def test2(cls):
print("class method test2, Hey test")
def test3(self):
print("instance method test3, Hey test")
Look what happens when you call test1 with the class or with the instance:
First:
TestClass.test1() #called from class
class method test1, Hey test
TestClass().test1() #created an instance TestClass()
Traceback (most recent call last):
File "python", line 1, in <module>
TypeError: test1() takes 0 positional arguments but 1 was given
that's because when you create an instance, the self
parameter is used, but here, the method has not the self parameter, that's why it brakes.
next one!
TestClass.test2()
class method test2, Hey test
TestClass().test2()
class method test2, Hey test
That worked for instance and for class, why? well, as you can see test2(cls) take an argument, cls
, here, I'm not using it, so, it's ok that it works.
bring me the next subject, muajaja
TestClass().test3()
instance method test3, Hey test
TestClass.test3()
Traceback (most recent call last):
File "python", line 1, in <module>
TypeError: test3() missing 1 required positional argument: 'self'
That's easy to see, when you call it as class, you haven't provided the self parameter
add a comment |
In python 3, there is no difference between a function and a function defined in a class:
def test():
print("Hey test")
class TestClass:
def test():
print("Hey test")
test() # works
TestClass.test() # also works
Both of these are normal functions.
The magic of the implicit self
argument happens when you access a function through an instance of the class, like this:
obj = TestClass()
obj.test() # throws an error because the test function doesn't accept arguments
This is when the function test
is turned into the method test
. You can see the difference if you print them:
print(TestClass.test)
print(instance.test)
# output:
# <function TestClass.test at 0xaaaaaa>
# <bound method TestClass.test of <__main__.TestClass object at 0xbbbbbb>>
To sum it up:
- Accessing a function through the class gives you the original function
- Accessing a function through an instance gives you a method with a bound
self
argument
add a comment |
Python 3 dispensed with the distinction between a bound and unbound method that existed in Python 2. What was previously an unbound method is now just a regular function.
class A(object):
def test():
pass
In Python 2:
>>> A.test
<unbound method A.test>
whereas in Python 3:
>>> A.test
<function A.test at 0x101cbbae8>
(the address may differ)
test
here is a descriptor; you don't (necessarily) get back the original function object when you access A.test
; instead you get the return value of that object's (i.e. the function's) __get__
method, which is called with two arguments. Which arguments depends on whether you access it via the class or via an instance of a class.
A.test
=>A.test.__get__(None, A)
a = A(); a.test
=>A.test.__get__(a, A)
In Python 2, A.test.__get__(None, A)
returns an method
object, which is a wrapper around the original function. As an unbound method
, the wrapper still expects an instance of A
as its first argument, even though the function itself was not defined with any parameters.
In Python 3, however, A.test.__get(None, A)
simply returns a reference to the original function, not a method
object. As a result, you can use it exactly as you defined it in the first place.
You can confirm this by examining id(A.__dict__['test'])
and id(A.test)
in Python 2 and Python 3. In Python 2, you'll get two different values; in Python 3, you'll get the same value for each.
add a comment |
TestClass.test()
call actually executes the test()
on the class object. This is similar to a @staticmethod (a method that can be executed on the class object, without creating an object first).
ins = TestClass()
ins.test()
will throw an exception, since instance methods pass self as the first argument, and test() takes no args.
When an object is created, the methods defined in the clas are bound to it. They are actually different objects, hence they have different ids:
id(TestClass.test)
=> 140288592901800
obj = TestClass()
id(obj.test)
=> 140288605765960
In Python 2.7, your code throws an exception which is self explantory:
Traceback (most recent call last):
File "<pyshell#404>", line 1, in <module>
TestClass.test()
TypeError: unbound method test() must be called with TestClass instance as
first argument (got nothing instead)
@staticmethod may be called from instances of the class, but in my example it isn't possible
– Gusev Slava
Nov 1 '17 at 12:19
That's because when anything is called on an instance method, the self part is passed automatically. If your function don't take any args, you simply can't execute it on an instance object.
– Chen A.
Nov 1 '17 at 14:36
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f47054156%2finner-class-function-without-self%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
In Python 3, (unlike Python 2) a function accessed and called from the class is just another function; nothing special:
Note that the transformation from function object to instance method
object happens each time the attribute is retrieved from the instance.
[Emphasis mine]
You just happened to be calling the function with the right set of parameters albeit accessed via the class object. Same as calling the underlying function object for the method via an instance:
TestClass().test.__func__() # "Hey test"
A quick test explains it further:
print(TestClass().test is TestClass.test)
# False
print(TestClass().test.__func__ is TestClass.test)
# True
However, in Python 2, the behaviour is different as the transformation from function object to method object happens when the attribute is accessed via both the class or instance:
Note that the transformation from function object to (unbound or
bound) method object happens each time the attribute is retrieved from
the class or instance.
[Emphasis mine]
add a comment |
In Python 3, (unlike Python 2) a function accessed and called from the class is just another function; nothing special:
Note that the transformation from function object to instance method
object happens each time the attribute is retrieved from the instance.
[Emphasis mine]
You just happened to be calling the function with the right set of parameters albeit accessed via the class object. Same as calling the underlying function object for the method via an instance:
TestClass().test.__func__() # "Hey test"
A quick test explains it further:
print(TestClass().test is TestClass.test)
# False
print(TestClass().test.__func__ is TestClass.test)
# True
However, in Python 2, the behaviour is different as the transformation from function object to method object happens when the attribute is accessed via both the class or instance:
Note that the transformation from function object to (unbound or
bound) method object happens each time the attribute is retrieved from
the class or instance.
[Emphasis mine]
add a comment |
In Python 3, (unlike Python 2) a function accessed and called from the class is just another function; nothing special:
Note that the transformation from function object to instance method
object happens each time the attribute is retrieved from the instance.
[Emphasis mine]
You just happened to be calling the function with the right set of parameters albeit accessed via the class object. Same as calling the underlying function object for the method via an instance:
TestClass().test.__func__() # "Hey test"
A quick test explains it further:
print(TestClass().test is TestClass.test)
# False
print(TestClass().test.__func__ is TestClass.test)
# True
However, in Python 2, the behaviour is different as the transformation from function object to method object happens when the attribute is accessed via both the class or instance:
Note that the transformation from function object to (unbound or
bound) method object happens each time the attribute is retrieved from
the class or instance.
[Emphasis mine]
In Python 3, (unlike Python 2) a function accessed and called from the class is just another function; nothing special:
Note that the transformation from function object to instance method
object happens each time the attribute is retrieved from the instance.
[Emphasis mine]
You just happened to be calling the function with the right set of parameters albeit accessed via the class object. Same as calling the underlying function object for the method via an instance:
TestClass().test.__func__() # "Hey test"
A quick test explains it further:
print(TestClass().test is TestClass.test)
# False
print(TestClass().test.__func__ is TestClass.test)
# True
However, in Python 2, the behaviour is different as the transformation from function object to method object happens when the attribute is accessed via both the class or instance:
Note that the transformation from function object to (unbound or
bound) method object happens each time the attribute is retrieved from
the class or instance.
[Emphasis mine]
edited Nov 1 '17 at 12:12
answered Nov 1 '17 at 11:59
Moses KoledoyeMoses Koledoye
62.4k75979
62.4k75979
add a comment |
add a comment |
Let me explain with an example:
class TestClass(object):
def __init__(self):
self.arg = "arg"
def test1():
print("class method test1, Hey test")
@classmethod
def test2(cls):
print("class method test2, Hey test")
def test3(self):
print("instance method test3, Hey test")
Look what happens when you call test1 with the class or with the instance:
First:
TestClass.test1() #called from class
class method test1, Hey test
TestClass().test1() #created an instance TestClass()
Traceback (most recent call last):
File "python", line 1, in <module>
TypeError: test1() takes 0 positional arguments but 1 was given
that's because when you create an instance, the self
parameter is used, but here, the method has not the self parameter, that's why it brakes.
next one!
TestClass.test2()
class method test2, Hey test
TestClass().test2()
class method test2, Hey test
That worked for instance and for class, why? well, as you can see test2(cls) take an argument, cls
, here, I'm not using it, so, it's ok that it works.
bring me the next subject, muajaja
TestClass().test3()
instance method test3, Hey test
TestClass.test3()
Traceback (most recent call last):
File "python", line 1, in <module>
TypeError: test3() missing 1 required positional argument: 'self'
That's easy to see, when you call it as class, you haven't provided the self parameter
add a comment |
Let me explain with an example:
class TestClass(object):
def __init__(self):
self.arg = "arg"
def test1():
print("class method test1, Hey test")
@classmethod
def test2(cls):
print("class method test2, Hey test")
def test3(self):
print("instance method test3, Hey test")
Look what happens when you call test1 with the class or with the instance:
First:
TestClass.test1() #called from class
class method test1, Hey test
TestClass().test1() #created an instance TestClass()
Traceback (most recent call last):
File "python", line 1, in <module>
TypeError: test1() takes 0 positional arguments but 1 was given
that's because when you create an instance, the self
parameter is used, but here, the method has not the self parameter, that's why it brakes.
next one!
TestClass.test2()
class method test2, Hey test
TestClass().test2()
class method test2, Hey test
That worked for instance and for class, why? well, as you can see test2(cls) take an argument, cls
, here, I'm not using it, so, it's ok that it works.
bring me the next subject, muajaja
TestClass().test3()
instance method test3, Hey test
TestClass.test3()
Traceback (most recent call last):
File "python", line 1, in <module>
TypeError: test3() missing 1 required positional argument: 'self'
That's easy to see, when you call it as class, you haven't provided the self parameter
add a comment |
Let me explain with an example:
class TestClass(object):
def __init__(self):
self.arg = "arg"
def test1():
print("class method test1, Hey test")
@classmethod
def test2(cls):
print("class method test2, Hey test")
def test3(self):
print("instance method test3, Hey test")
Look what happens when you call test1 with the class or with the instance:
First:
TestClass.test1() #called from class
class method test1, Hey test
TestClass().test1() #created an instance TestClass()
Traceback (most recent call last):
File "python", line 1, in <module>
TypeError: test1() takes 0 positional arguments but 1 was given
that's because when you create an instance, the self
parameter is used, but here, the method has not the self parameter, that's why it brakes.
next one!
TestClass.test2()
class method test2, Hey test
TestClass().test2()
class method test2, Hey test
That worked for instance and for class, why? well, as you can see test2(cls) take an argument, cls
, here, I'm not using it, so, it's ok that it works.
bring me the next subject, muajaja
TestClass().test3()
instance method test3, Hey test
TestClass.test3()
Traceback (most recent call last):
File "python", line 1, in <module>
TypeError: test3() missing 1 required positional argument: 'self'
That's easy to see, when you call it as class, you haven't provided the self parameter
Let me explain with an example:
class TestClass(object):
def __init__(self):
self.arg = "arg"
def test1():
print("class method test1, Hey test")
@classmethod
def test2(cls):
print("class method test2, Hey test")
def test3(self):
print("instance method test3, Hey test")
Look what happens when you call test1 with the class or with the instance:
First:
TestClass.test1() #called from class
class method test1, Hey test
TestClass().test1() #created an instance TestClass()
Traceback (most recent call last):
File "python", line 1, in <module>
TypeError: test1() takes 0 positional arguments but 1 was given
that's because when you create an instance, the self
parameter is used, but here, the method has not the self parameter, that's why it brakes.
next one!
TestClass.test2()
class method test2, Hey test
TestClass().test2()
class method test2, Hey test
That worked for instance and for class, why? well, as you can see test2(cls) take an argument, cls
, here, I'm not using it, so, it's ok that it works.
bring me the next subject, muajaja
TestClass().test3()
instance method test3, Hey test
TestClass.test3()
Traceback (most recent call last):
File "python", line 1, in <module>
TypeError: test3() missing 1 required positional argument: 'self'
That's easy to see, when you call it as class, you haven't provided the self parameter
edited Nov 23 '18 at 7:00
thepurpleowl
99112
99112
answered Nov 1 '17 at 11:55
Damian LatteneroDamian Lattenero
9,09021944
9,09021944
add a comment |
add a comment |
In python 3, there is no difference between a function and a function defined in a class:
def test():
print("Hey test")
class TestClass:
def test():
print("Hey test")
test() # works
TestClass.test() # also works
Both of these are normal functions.
The magic of the implicit self
argument happens when you access a function through an instance of the class, like this:
obj = TestClass()
obj.test() # throws an error because the test function doesn't accept arguments
This is when the function test
is turned into the method test
. You can see the difference if you print them:
print(TestClass.test)
print(instance.test)
# output:
# <function TestClass.test at 0xaaaaaa>
# <bound method TestClass.test of <__main__.TestClass object at 0xbbbbbb>>
To sum it up:
- Accessing a function through the class gives you the original function
- Accessing a function through an instance gives you a method with a bound
self
argument
add a comment |
In python 3, there is no difference between a function and a function defined in a class:
def test():
print("Hey test")
class TestClass:
def test():
print("Hey test")
test() # works
TestClass.test() # also works
Both of these are normal functions.
The magic of the implicit self
argument happens when you access a function through an instance of the class, like this:
obj = TestClass()
obj.test() # throws an error because the test function doesn't accept arguments
This is when the function test
is turned into the method test
. You can see the difference if you print them:
print(TestClass.test)
print(instance.test)
# output:
# <function TestClass.test at 0xaaaaaa>
# <bound method TestClass.test of <__main__.TestClass object at 0xbbbbbb>>
To sum it up:
- Accessing a function through the class gives you the original function
- Accessing a function through an instance gives you a method with a bound
self
argument
add a comment |
In python 3, there is no difference between a function and a function defined in a class:
def test():
print("Hey test")
class TestClass:
def test():
print("Hey test")
test() # works
TestClass.test() # also works
Both of these are normal functions.
The magic of the implicit self
argument happens when you access a function through an instance of the class, like this:
obj = TestClass()
obj.test() # throws an error because the test function doesn't accept arguments
This is when the function test
is turned into the method test
. You can see the difference if you print them:
print(TestClass.test)
print(instance.test)
# output:
# <function TestClass.test at 0xaaaaaa>
# <bound method TestClass.test of <__main__.TestClass object at 0xbbbbbb>>
To sum it up:
- Accessing a function through the class gives you the original function
- Accessing a function through an instance gives you a method with a bound
self
argument
In python 3, there is no difference between a function and a function defined in a class:
def test():
print("Hey test")
class TestClass:
def test():
print("Hey test")
test() # works
TestClass.test() # also works
Both of these are normal functions.
The magic of the implicit self
argument happens when you access a function through an instance of the class, like this:
obj = TestClass()
obj.test() # throws an error because the test function doesn't accept arguments
This is when the function test
is turned into the method test
. You can see the difference if you print them:
print(TestClass.test)
print(instance.test)
# output:
# <function TestClass.test at 0xaaaaaa>
# <bound method TestClass.test of <__main__.TestClass object at 0xbbbbbb>>
To sum it up:
- Accessing a function through the class gives you the original function
- Accessing a function through an instance gives you a method with a bound
self
argument
answered Nov 1 '17 at 12:22
Aran-FeyAran-Fey
20.4k53871
20.4k53871
add a comment |
add a comment |
Python 3 dispensed with the distinction between a bound and unbound method that existed in Python 2. What was previously an unbound method is now just a regular function.
class A(object):
def test():
pass
In Python 2:
>>> A.test
<unbound method A.test>
whereas in Python 3:
>>> A.test
<function A.test at 0x101cbbae8>
(the address may differ)
test
here is a descriptor; you don't (necessarily) get back the original function object when you access A.test
; instead you get the return value of that object's (i.e. the function's) __get__
method, which is called with two arguments. Which arguments depends on whether you access it via the class or via an instance of a class.
A.test
=>A.test.__get__(None, A)
a = A(); a.test
=>A.test.__get__(a, A)
In Python 2, A.test.__get__(None, A)
returns an method
object, which is a wrapper around the original function. As an unbound method
, the wrapper still expects an instance of A
as its first argument, even though the function itself was not defined with any parameters.
In Python 3, however, A.test.__get(None, A)
simply returns a reference to the original function, not a method
object. As a result, you can use it exactly as you defined it in the first place.
You can confirm this by examining id(A.__dict__['test'])
and id(A.test)
in Python 2 and Python 3. In Python 2, you'll get two different values; in Python 3, you'll get the same value for each.
add a comment |
Python 3 dispensed with the distinction between a bound and unbound method that existed in Python 2. What was previously an unbound method is now just a regular function.
class A(object):
def test():
pass
In Python 2:
>>> A.test
<unbound method A.test>
whereas in Python 3:
>>> A.test
<function A.test at 0x101cbbae8>
(the address may differ)
test
here is a descriptor; you don't (necessarily) get back the original function object when you access A.test
; instead you get the return value of that object's (i.e. the function's) __get__
method, which is called with two arguments. Which arguments depends on whether you access it via the class or via an instance of a class.
A.test
=>A.test.__get__(None, A)
a = A(); a.test
=>A.test.__get__(a, A)
In Python 2, A.test.__get__(None, A)
returns an method
object, which is a wrapper around the original function. As an unbound method
, the wrapper still expects an instance of A
as its first argument, even though the function itself was not defined with any parameters.
In Python 3, however, A.test.__get(None, A)
simply returns a reference to the original function, not a method
object. As a result, you can use it exactly as you defined it in the first place.
You can confirm this by examining id(A.__dict__['test'])
and id(A.test)
in Python 2 and Python 3. In Python 2, you'll get two different values; in Python 3, you'll get the same value for each.
add a comment |
Python 3 dispensed with the distinction between a bound and unbound method that existed in Python 2. What was previously an unbound method is now just a regular function.
class A(object):
def test():
pass
In Python 2:
>>> A.test
<unbound method A.test>
whereas in Python 3:
>>> A.test
<function A.test at 0x101cbbae8>
(the address may differ)
test
here is a descriptor; you don't (necessarily) get back the original function object when you access A.test
; instead you get the return value of that object's (i.e. the function's) __get__
method, which is called with two arguments. Which arguments depends on whether you access it via the class or via an instance of a class.
A.test
=>A.test.__get__(None, A)
a = A(); a.test
=>A.test.__get__(a, A)
In Python 2, A.test.__get__(None, A)
returns an method
object, which is a wrapper around the original function. As an unbound method
, the wrapper still expects an instance of A
as its first argument, even though the function itself was not defined with any parameters.
In Python 3, however, A.test.__get(None, A)
simply returns a reference to the original function, not a method
object. As a result, you can use it exactly as you defined it in the first place.
You can confirm this by examining id(A.__dict__['test'])
and id(A.test)
in Python 2 and Python 3. In Python 2, you'll get two different values; in Python 3, you'll get the same value for each.
Python 3 dispensed with the distinction between a bound and unbound method that existed in Python 2. What was previously an unbound method is now just a regular function.
class A(object):
def test():
pass
In Python 2:
>>> A.test
<unbound method A.test>
whereas in Python 3:
>>> A.test
<function A.test at 0x101cbbae8>
(the address may differ)
test
here is a descriptor; you don't (necessarily) get back the original function object when you access A.test
; instead you get the return value of that object's (i.e. the function's) __get__
method, which is called with two arguments. Which arguments depends on whether you access it via the class or via an instance of a class.
A.test
=>A.test.__get__(None, A)
a = A(); a.test
=>A.test.__get__(a, A)
In Python 2, A.test.__get__(None, A)
returns an method
object, which is a wrapper around the original function. As an unbound method
, the wrapper still expects an instance of A
as its first argument, even though the function itself was not defined with any parameters.
In Python 3, however, A.test.__get(None, A)
simply returns a reference to the original function, not a method
object. As a result, you can use it exactly as you defined it in the first place.
You can confirm this by examining id(A.__dict__['test'])
and id(A.test)
in Python 2 and Python 3. In Python 2, you'll get two different values; in Python 3, you'll get the same value for each.
edited Nov 1 '17 at 13:23
answered Nov 1 '17 at 12:32
chepnerchepner
258k34249343
258k34249343
add a comment |
add a comment |
TestClass.test()
call actually executes the test()
on the class object. This is similar to a @staticmethod (a method that can be executed on the class object, without creating an object first).
ins = TestClass()
ins.test()
will throw an exception, since instance methods pass self as the first argument, and test() takes no args.
When an object is created, the methods defined in the clas are bound to it. They are actually different objects, hence they have different ids:
id(TestClass.test)
=> 140288592901800
obj = TestClass()
id(obj.test)
=> 140288605765960
In Python 2.7, your code throws an exception which is self explantory:
Traceback (most recent call last):
File "<pyshell#404>", line 1, in <module>
TestClass.test()
TypeError: unbound method test() must be called with TestClass instance as
first argument (got nothing instead)
@staticmethod may be called from instances of the class, but in my example it isn't possible
– Gusev Slava
Nov 1 '17 at 12:19
That's because when anything is called on an instance method, the self part is passed automatically. If your function don't take any args, you simply can't execute it on an instance object.
– Chen A.
Nov 1 '17 at 14:36
add a comment |
TestClass.test()
call actually executes the test()
on the class object. This is similar to a @staticmethod (a method that can be executed on the class object, without creating an object first).
ins = TestClass()
ins.test()
will throw an exception, since instance methods pass self as the first argument, and test() takes no args.
When an object is created, the methods defined in the clas are bound to it. They are actually different objects, hence they have different ids:
id(TestClass.test)
=> 140288592901800
obj = TestClass()
id(obj.test)
=> 140288605765960
In Python 2.7, your code throws an exception which is self explantory:
Traceback (most recent call last):
File "<pyshell#404>", line 1, in <module>
TestClass.test()
TypeError: unbound method test() must be called with TestClass instance as
first argument (got nothing instead)
@staticmethod may be called from instances of the class, but in my example it isn't possible
– Gusev Slava
Nov 1 '17 at 12:19
That's because when anything is called on an instance method, the self part is passed automatically. If your function don't take any args, you simply can't execute it on an instance object.
– Chen A.
Nov 1 '17 at 14:36
add a comment |
TestClass.test()
call actually executes the test()
on the class object. This is similar to a @staticmethod (a method that can be executed on the class object, without creating an object first).
ins = TestClass()
ins.test()
will throw an exception, since instance methods pass self as the first argument, and test() takes no args.
When an object is created, the methods defined in the clas are bound to it. They are actually different objects, hence they have different ids:
id(TestClass.test)
=> 140288592901800
obj = TestClass()
id(obj.test)
=> 140288605765960
In Python 2.7, your code throws an exception which is self explantory:
Traceback (most recent call last):
File "<pyshell#404>", line 1, in <module>
TestClass.test()
TypeError: unbound method test() must be called with TestClass instance as
first argument (got nothing instead)
TestClass.test()
call actually executes the test()
on the class object. This is similar to a @staticmethod (a method that can be executed on the class object, without creating an object first).
ins = TestClass()
ins.test()
will throw an exception, since instance methods pass self as the first argument, and test() takes no args.
When an object is created, the methods defined in the clas are bound to it. They are actually different objects, hence they have different ids:
id(TestClass.test)
=> 140288592901800
obj = TestClass()
id(obj.test)
=> 140288605765960
In Python 2.7, your code throws an exception which is self explantory:
Traceback (most recent call last):
File "<pyshell#404>", line 1, in <module>
TestClass.test()
TypeError: unbound method test() must be called with TestClass instance as
first argument (got nothing instead)
edited Nov 1 '17 at 12:02
answered Nov 1 '17 at 11:57
Chen A.Chen A.
5,33221634
5,33221634
@staticmethod may be called from instances of the class, but in my example it isn't possible
– Gusev Slava
Nov 1 '17 at 12:19
That's because when anything is called on an instance method, the self part is passed automatically. If your function don't take any args, you simply can't execute it on an instance object.
– Chen A.
Nov 1 '17 at 14:36
add a comment |
@staticmethod may be called from instances of the class, but in my example it isn't possible
– Gusev Slava
Nov 1 '17 at 12:19
That's because when anything is called on an instance method, the self part is passed automatically. If your function don't take any args, you simply can't execute it on an instance object.
– Chen A.
Nov 1 '17 at 14:36
@staticmethod may be called from instances of the class, but in my example it isn't possible
– Gusev Slava
Nov 1 '17 at 12:19
@staticmethod may be called from instances of the class, but in my example it isn't possible
– Gusev Slava
Nov 1 '17 at 12:19
That's because when anything is called on an instance method, the self part is passed automatically. If your function don't take any args, you simply can't execute it on an instance object.
– Chen A.
Nov 1 '17 at 14:36
That's because when anything is called on an instance method, the self part is passed automatically. If your function don't take any args, you simply can't execute it on an instance object.
– Chen A.
Nov 1 '17 at 14:36
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f47054156%2finner-class-function-without-self%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
why do you find that code strange?
– mast3rd3mon
Nov 1 '17 at 11:52
test
is a function taking no parameters and you're calling it without parameters. All good. Now,TestClass().test()
OTOH is a different story…– deceze♦
Nov 1 '17 at 11:53
3
Yes. It is very weird that it changed "Hey" to lowercase.
– stark
Nov 1 '17 at 11:55
3
Is the ambiguity of
self.test
a part of the question, or just a coincidence?– tobias_k
Nov 1 '17 at 12:00
@tobias_k sorry, it's just coincidence, i fix it
– Gusev Slava
Nov 1 '17 at 12:01