
Hi all,
Not sure if this subject has been brought up already, but why can't we redefine methods as such for example:
c = MyClass o = c()
def c.foo(cls): ... def o.bar(self): ...
Thanks in advance for sharing some of your insight

Hi Jamesie
Thank you for your question. You asked why not
c = MyClass o = c()
def c.foo(cls): ... def o.bar(self): ...
I've the same same query, but never had the courage to ask. So that you for asking. And also giving me a chance to share my thoughts.
In Ruby, I believe, you can 'open up' an existing class, and add new methods to it. You can even do with core classes. I think what you asking might amount to a wish to do the same in Python.
I think the Python way to 'open up' an existing class is to create a subclass, and add methods to that. Python design and development is quite pragmatic. So instead of us saying why it's not there, why don't you tell why you think it might be good idea. Based of course on examples. Particularly code taken from successful real-world applications.
By the way, your
def o.var(self): ...
won't work as you expect. To get a bound method, the method must be an attribute of the class (in other words type(o)) of the object o. That's the way Python is. What you've written does work in JavaScript.
It's perhaps a bit technical and short of examples, but https://docs.python.org/3/reference/datamodel.html would be a good starting point. Can anyone else recommend some other URLs for this.
Once again, thank you for asking this question. I look forward to reading other answers (and of course your response).

On 31 July 2018 at 01:35, Jonathan Fine jfine2358@gmail.com wrote:
Hi Jamesie
Thank you for your question. You asked why not
c = MyClass o = c()
def c.foo(cls): ... def o.bar(self): ...
I've the same same query, but never had the courage to ask. So that you for asking. And also giving me a chance to share my thoughts.
It's essentially due to the fact that while we deliberately allow runtime monkeypatching (as it's sometimes the best available answer), we also strongly encourage the idea of treating it as a last resort option (outside specific use cases like testing).
So if you want to define methods on a class, the strongly preferred place to define them is inside the class definition, where they're easy for future maintainers of that class to find.
If you need to replace them for some reason, it will preferably be within a temporary bounded scope, using a tool like unittest.mock.patch, rather than as a permanent change that affects every other use of the class within the process.
Cheers, Nick.
P.S. While it's *not* explicitly part of Python's design rationale, http://connascence.io/locality.html and the rest of that site provide some good info on the kinds of problems that "action at a distance" effects, like monkeypatching class definitions, can cause in a code base.

On Mon, Jul 30, 2018 at 9:10 AM, Nick Coghlan ncoghlan@gmail.com wrote:
If you need to replace them for some reason, it will preferably be
within a temporary bounded scope, using a tool like unittest.mock.patch, rather than as a permanent change that affects every other use of the class within the process.
yup -- but you can still do a raw monkey-patch anyway. You asked for:
Thank you for your question. You asked why not
c = MyClass o = c()
def c.foo(cls): ...
do you mean this? you want a classmethod? or is this what you mean? -- which you can do:
C = MyClass
def foo(self, some_param): some_code()
C.foo = foo
(note that I used a capital C -- capitalized names are traditional for classes -- see PEP 8)
In that case, any existing, and new instances of the C class will now have the foo method.
Also -- that line: C = MyClass -- binds the name "C" to the very same class object as MyClass -- so you will have just monkey=patched MyClass -- I"m guessing you didn't want that. If not, and you wanted C t be a copy of MyClass that you could then change/add/remove methods from, then you want subclassing -- that is exactly what it is for.
Then there is this:
def o.bar(self): ...
which is monkey patching an instance object, which you can also do, but you don't get a bound method -- i.e. it doesn't get self passed in automatically.
-CHB
I've the same same query, but never had the courage to ask. So that you for asking. And also giving me a chance to share my thoughts.
It's essentially due to the fact that while we deliberately allow runtime monkeypatching (as it's sometimes the best available answer), we also strongly encourage the idea of treating it as a last resort option (outside specific use cases like testing).
So if you want to define methods on a class, the strongly preferred place to define them is inside the class definition, where they're easy for future maintainers of that class to find.
Cheers, Nick.
P.S. While it's *not* explicitly part of Python's design rationale, http://connascence.io/locality.html and the rest of that site provide some good info on the kinds of problems that "action at a distance" effects, like monkeypatching class definitions, can cause in a code base.
-- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/

I think C# calls methods that are added to a class "extension methods". You can make a decorator that will do that for you:
def extend(cls): """ DECORATOR TO ADD METHODS TO CLASSES :param cls: THE CLASS TO ADD THE METHOD TO :return: """ def extender(func): setattr(cls, get_function_name(func), func) return func return extender
and use it
C = MyClass @extend(C) def foo(self, schesome_param): some_code()
On 2018-07-30 14:12, Chris Barker via Python-ideas wrote:
On Mon, Jul 30, 2018 at 9:10 AM, Nick Coghlan <ncoghlan@gmail.com mailto:ncoghlan@gmail.com> wrote:
If you need to replace them for some reason, it will preferably be within a temporary bounded scope, using a tool like unittest.mock.patch, rather than as a permanent change that affects every other use of the class within the process.
yup -- but you can still do a raw monkey-patch anyway. You asked for:
> Thank you for your question. You asked why not >> c = MyClass >> o = c() >> >> def c.foo(cls): ...
do you mean this? you want a classmethod? or is this what you mean? -- which you can do:
C = MyClass
def foo(self, some_param): some_code()
C.foo = foo
(note that I used a capital C -- capitalized names are traditional for classes -- see PEP 8)
In that case, any existing, and new instances of the C class will now have the foo method.
Also -- that line: C = MyClass -- binds the name "C" to the very same class object as MyClass -- so you will have just monkey=patched MyClass -- I"m guessing you didn't want that. If not, and you wanted C t be a copy of MyClass that you could then change/add/remove methods from, then you want subclassing -- that is exactly what it is for.
Then there is this:
>> def o.bar(self): ...
which is monkey patching an instance object, which you can also do, but you don't get a bound method -- i.e. it doesn't get self passed in automatically.
-CHB
> I've the same same query, but never had the courage to ask. So that > you for asking. And also giving me a chance to share my thoughts. It's essentially due to the fact that while we deliberately allow runtime monkeypatching (as it's sometimes the best available answer), we also strongly encourage the idea of treating it as a last resort option (outside specific use cases like testing). So if you want to define methods on a class, the strongly preferred place to define them is inside the class definition, where they're easy for future maintainers of that class to find. Cheers, Nick. P.S. While it's *not* explicitly part of Python's design rationale, http://connascence.io/locality.html <http://connascence.io/locality.html> and the rest of that site provide some good info on the kinds of problems that "action at a distance" effects, like monkeypatching class definitions, can cause in a code base. -- Nick Coghlan | ncoghlan@gmail.com <mailto:ncoghlan@gmail.com> | Brisbane, Australia _______________________________________________ Python-ideas mailing list Python-ideas@python.org <mailto:Python-ideas@python.org> https://mail.python.org/mailman/listinfo/python-ideas <https://mail.python.org/mailman/listinfo/python-ideas> Code of Conduct: http://python.org/psf/codeofconduct/ <http://python.org/psf/codeofconduct/>
--
Christopher Barker, Ph.D. Oceanographer
Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception
Chris.Barker@noaa.gov mailto:Chris.Barker@noaa.gov
Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/

I like type() a lot, and the attributes dict it takes as argument works with lambda.
My use case is just a python module for a framework provides a default instance for some model, and I thought it would be cool to just change a method without going through
I'm really bad at defending ideas, specially in English, but I have one statement to try:
How exciting is life if you're not monkey patching runtime on a daily basis ?
Cheers

Sorry if my message offended anyone (noted that the "Toxic Forum" post came not long after mine).
What I meant is that I cannot defend such an idea before extensively using it. I just don't know how to do it this way.
Have a great day

Jamesie Pic wrote:
def o.bar(self): ...
You could get almost the same effect with
from functools import partial
def bar(self, other_args): ...
o.bar = partial(bar, o)
But IMO this is nowhere near being a common enough thing to do to justify having special syntax for it.

On Tue, Jul 31, 2018 at 10:10:32AM +1200, Greg Ewing wrote:
Jamesie Pic wrote:
def o.bar(self): ...
You could get almost the same effect with
from functools import partial
def bar(self, other_args): ...
o.bar = partial(bar, o)
Why are you using functools.partial instead of types.MethodType? I'm wondering if there is some advantage to partial that I don't recognise.
I'm not sure if there's a functional difference between the two approaches, but it makes o.bar a different kind of callable and that will probably make a difference to somebody.
But IMO this is nowhere near being a common enough thing to do to justify having special syntax for it.
This sort of thing isn't common because there's no neat, easy, obvious, built-in way to do it. If we allowed people to extend classes using the syntax
def classobj.methodname(...): ...
def instance.methodname(...): ...
people would use the technique more. For good or ill.
I don't question the utility of this technique, but I suspect we prefer to *slightly* discourage it by *not* providing a Batteries Included solution for this. If you want to do this, we won't stop you, but neither will we encourage it by supporting it in syntax or providing a standard decorator for it.

Here is an example of how it could be done.
https://gist.github.com/stephanh42/97b47506e5e416f97f5790c070be7878
Stephan
Op di 31 jul. 2018 01:29 schreef Steven D'Aprano steve@pearwood.info:
On Tue, Jul 31, 2018 at 10:10:32AM +1200, Greg Ewing wrote:
Jamesie Pic wrote:
def o.bar(self): ...
You could get almost the same effect with
from functools import partial
def bar(self, other_args): ...
o.bar = partial(bar, o)
Why are you using functools.partial instead of types.MethodType? I'm wondering if there is some advantage to partial that I don't recognise.
I'm not sure if there's a functional difference between the two approaches, but it makes o.bar a different kind of callable and that will probably make a difference to somebody.
But IMO this is nowhere near being a common enough thing to do to justify having special syntax for it.
This sort of thing isn't common because there's no neat, easy, obvious, built-in way to do it. If we allowed people to extend classes using the syntax
def classobj.methodname(...): ... def instance.methodname(...): ...
people would use the technique more. For good or ill.
I don't question the utility of this technique, but I suspect we prefer to *slightly* discourage it by *not* providing a Batteries Included solution for this. If you want to do this, we won't stop you, but neither will we encourage it by supporting it in syntax or providing a standard decorator for it.
-- Steve _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
participants (8)
-
Chris Barker
-
Greg Ewing
-
Jamesie Pic
-
Jonathan Fine
-
Kyle Lahnakoski
-
Nick Coghlan
-
Stephan Houben
-
Steven D'Aprano