-
-
Notifications
You must be signed in to change notification settings - Fork 30.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
report very strange behavior of user-defined class lambda function #126666
Comments
Lambdas are regular functions, just with no name set. And if you have a function defined in a class which you access on the instance, you get a bound method. To stop that you'll need to wrap it in a |
To make @TeamSpen210's comment more explicit, your lambda is just a different way to spell this, which acts the same way in all respects: def fn_a(x):
return x Which in turn works the same as: def fn_a(self):
return self That is, there's nothing magical about the name "self" either - the first argument to a method is just usually named "self" by convention. Spelling it "x" instead is fine (just unusual). |
Just to keep an explicit example: >>> class X:
... fn_a = staticmethod(lambda x: x)
... def test(self):
... print(f'{type(self.fn_a)=}')
... assert self.fn_a(1) == 1
...
>>> X().test()
type(self.fn_a)=<class 'function'> I think this can be closed. |
thank you all! in
the
the when we define another class function
we can use like this:
both I don't known what is making the difference, it not so straightforward |
Maybe the key point is: the doing-things of actually, if
fn_a IS a member of class X, and the result of self.fn_a SHOULD be lambda x: x, so: self.fn_a(1) is LEGAL, self.fn_a() NOT legal |
Because cls_test in this example is a class method. cls.fn_a - reference to the class function fn_a, i.e. >>> class A:
... f = lambda x: x
...
>>> A.f
<function A.<lambda> at 0x7f7cf5e67890>
>>> A().f
<bound method A.<lambda> of <__main__.A object at 0x7f7cf5e03600>>
>>> A.__dict__['f']
<function A.<lambda> at 0x7f7cf5e67890>
>>> import inspect
>>> inspect.signature(A.f)
<Signature (x)>
>>> inspect.signature(A().f)
<Signature ()> |
Thank very much, I started a new discussion in: Maybe we should define class method more explicitly just like @skirpichev mentioned
Other than:
the current default behavior make too much confusion. Looking forward to your opinion: |
This is valid syntax. It makes
This makes Functions in Python have a special method
I hid the object addresses because they don't matter. We might get the same address or different addresses depending on Python's internal memory management. Every time that we do Yes, I said " Anyway, a "method" is just a function object that belongs to the class itself. A "method call" works because looking for the function finds it in the class, and then automatically creates that "bound method" object. Calling that object does the rest of the work. This is called the descriptor protocol. There is much more detail in the documentation. It is complex. But it allows you to write simple code for simple tasks while not needing special cases - and it also makes things like Notice, it does not matter what we name the method. It does not matter what we name the parameters (including the first one: names like What matters is:
From the Discourse thread: the reason you get a different result with the callable object
is because
now when we look up If you want to use just the function and have the same parameters whether you look it up from an instance or directly in the class, that is what
|
Bug report
Bug description:
It is very HARD to define a pure lambda function in class, the result is unexpected.
I’m not sure if it was intentionally designed this way or if I missed something.
CPython versions tested on:
3.12
Operating systems tested on:
macOS
Tasks
The text was updated successfully, but these errors were encountered: