一个类方法,当作为实例方法调用时,行为不同? [英] A class method which behaves differently when called as an instance method?
问题描述
我想知道是否有可能使一个方法在作为类方法调用时比作为实例方法调用时有所不同。
I'm wondering if it's possible to make a method which behaves differently when called as a class method than when called as an instance method.
例如,一个技能改进项目,我写一个 Matrix
类(是的,我知道有完美的矩阵类已经有)。我创建了一个名为 identity
的类方法,它返回指定大小的单位矩阵。
For example, as a skills-improvement project, I'm writing a Matrix
class (yes, I know there are perfectly good matrix classes already out there). I've created a class method for it called identity
which returns an identity matrix of a specified size.
,当在 Matrix
的实例上调用时,似乎不需要指定大小,它应该返回一个与 Matrix
相同大小的单位矩阵。
Now, when called on an instance of Matrix
, it seems logical that the size shouldn't need to be specified; it should return an identity matrix of the same size as the Matrix
it's called on.
换句话说,I喜欢定义一个方法,可以确定它是否通过实例调用,如果是,访问该实例的属性。不幸的是,即使通过文档和几个Google搜索,我还没有找到任何建议这是可能的。有谁知道不同?
In other words, I'd like to define a method which can determine whether it was called via an instance and, if so, access that instance's attributes. Unfortunately, even after digging through the documentation and a few Google searches, I haven't found anything which suggests this is possible. Does anyone know differently?
编辑:
显然,我还是不习惯一流的函数。
Wow! Clearly, I'm still not quite used to first-class functions. Here's what I ended up with — thanks to Unknown for providing the key!
class Foo(object):
def __init__(self, bar):
self.baz = bar
self.bar = MethodType(lambda self: self.__class__.bar(self.baz), self, self.__class__)
@classmethod
def bar(cls, baz):
return 5 * baz
Foo.bar(3) # returns 15
foo = Foo(7)
foo.bar() # returns 35
Edit 2:
只是一个快速注释 - 这种技术(和下面的大多数)不能用于定义<$ c $
Just a quick note — this technique (and most of those presented below) won't work on classes which define __slots__
, as you cannot reassign the method.
推荐答案
有问题的Python黑客是我的forte 。
Questionably useful Python hacks are my forte.
from types import *
class Foo(object):
def __init__(self):
self.bar = methodize(bar, self)
self.baz = 999
@classmethod
def bar(cls, baz):
return 2 * baz
def methodize(func, instance):
return MethodType(func, instance, instance.__class__)
def bar(self):
return 4*self.baz
>>> Foo.bar(5)
10
>>> a=Foo()
>>> a.bar()
3996
这篇关于一个类方法,当作为实例方法调用时,行为不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!