我被卡住了.我正在尝试动态定义一个类方法,我无法绕过ruby元类模型.考虑以下课程:
class Example
def self.meta; (class << self; self; end); end
def self.class_instance; self; end
end
Example.class_instance.class # => Class
Example.meta.class # => Class
Example.class_instance == Example # => true
Example.class_instance == Example.meta # => false
Run Code Online (Sandbox Code Playgroud)
显然,这两个方法都返回Class的实例.但这两个实例并不相同.他们也有不同的祖先:
Example.meta.ancestors # => [Class, Module, Object, Kernel]
Example.class_instance.ancestors # => [Example, Object, Kernel]
Run Code Online (Sandbox Code Playgroud)
在元类和类实例之间做出改变有什么意义?
我想,我可以send :define_method向元类动态定义一个方法,但是如果我尝试将它发送到类实例它将无法工作.至少我可以解决我的问题,但我仍然想知道它为什么这样工作.
更新2010年3月15日13:40
以下假设是否正确.
我觉得它开始对我有意义了.如果类方法中的self指向特征类,那肯定会限制你的可能性.如果是这样,就无法从类方法中定义实例方法.那是对的吗?
类的本征类(或元类)中的类方法和方法只有两种方法来定义一个东西吗?
否则,有什么区别?
class X
# class method
def self.a
"a"
end
# eigenclass method
class << self
def b
"b"
end
end
end
Run Code Online (Sandbox Code Playgroud)
难道X.a和X.b不同的表现以任何方式?
我认识到我可以通过打开特征类来覆盖或别名类方法:
irb(main):031:0> class X; def self.a; "a"; end; end
=> nil
irb(main):032:0> class X; class << self; alias_method :b, :a; end; end
=> #<Class:X>
irb(main):033:0> X.a
=> "a"
irb(main):034:0> X.b
=> "a"
irb(main):035:0> class X; class << self; def a; "c"; end; end; end
=> nil
irb(main):036:0> X.a
=> "c"
Run Code Online (Sandbox Code Playgroud) 我想只在加载一个类(而不是每个对象!)时合并当前和继承类的约束.
class Domain(Validatable):
constraints = {...}
Run Code Online (Sandbox Code Playgroud)
为此,我定义了一个_initialize_class_not_instance应该为每个类调用一次的方法:
class Validatable:
@classmethod
def _initialize_class_not_instance(cls):
# merge constraints from derived class and base classes
pass
__class__._initialize_class_not_instance() # doesn't work
# Validatable._merge_constraints() # doesn't work too
Run Code Online (Sandbox Code Playgroud)
问题是__class__在这种情况下不存在,Validatable也没有定义.但是我想避免,我的API的用户必须明确地调用initialize方法或者必须使用额外的类装饰器.
任何想法如何初始化类?
我有一个定义了常量的类.然后我定义了一个访问该类常量的类方法.这很好用.一个例子:
#! /usr/bin/env ruby
class NonInstantiableClass
Const = "hello, world!"
class << self
def shout_my_constant
puts Const.upcase
end
end
end
NonInstantiableClass.shout_my_constant
Run Code Online (Sandbox Code Playgroud)
我的问题出现在尝试将此类方法移出到外部模块,如下所示:
#! /usr/bin/env ruby
module CommonMethods
def shout_my_constant
puts Const.upcase
end
end
class NonInstantiableClass
Const = "hello, world!"
class << self
include CommonMethods
end
end
NonInstantiableClass.shout_my_constant
Run Code Online (Sandbox Code Playgroud)
Ruby将方法解释为从模块而不是类中请求常量:
line 5:in `shout_my_constant': uninitialized constant CommonMethods::Const (NameError)
Run Code Online (Sandbox Code Playgroud)
那么,你的伙伴们有什么神奇的技巧让方法访问类不变?非常感谢.
我有一个对象层次结构,其中几乎所有方法都是类方法.它看起来如下:
class ParentObject(object):
def __init__(self):
pass
@classmethod
def smile_warmly(cls, the_method):
def wrapper(kls, *args, **kwargs):
print "-smile_warmly - "+kls.__name__
the_method(*args, **kwargs)
return wrapper
@classmethod
def greetings(cls):
print "greetings"
class SonObject(ParentObject):
@classmethod
def hello_son(cls):
print "hello son"
@classmethod
def goodbye(cls):
print "goodbye son"
class DaughterObject(ParentObject):
@classmethod
def hello_daughter(cls):
print "hello daughter"
@classmethod
def goodbye(cls):
print "goodbye daughter"
if __name__ == '__main__':
son = SonObject()
son.greetings()
son.hello_son()
son.goodbye()
daughter = DaughterObject()
daughter.greetings()
daughter.hello_daughter()
daughter.goodbye()
Run Code Online (Sandbox Code Playgroud)
给定的代码输出如下:
greetings
hello son
goodbye son
greetings
hello daughter …Run Code Online (Sandbox Code Playgroud) TL; DR如何确定函数是使用定义@classmethod还是具有相同效果的函数?
我的问题
为了实现类装饰器,我想检查一个方法是否将类作为其第一个参数,例如,实现了via
@classmethod
def function(cls, ...):
Run Code Online (Sandbox Code Playgroud)
我发现了一个解决方案,以检查@staticmethod通过types模块(isinstance(foo, types.UnboundMethodType)是False,如果foo是静态的,见这里),但没有找到如何做到这一点的任何东西@classmethod
上下文
我想要做的是一些事情
def class_decorator(cls):
for member in cls.__dict__:
if (isclassmethod(getattr(cls, member))):
# do something with the method
setattr(cls, member, modified_method)
return cls
Run Code Online (Sandbox Code Playgroud)
我不知道如何实现我isclassmethod在这个例子中所谓的内容
我想在我的泛型中设置一些标志(在调用之前UseMethod(),我知道很多:)),然后在方法中使用和/或更新这些标志.
像这样:
g <- function(x) {
y <- 10
UseMethod("g")
}
g.default <- function(x) {
c(x = x, y = y)
}
g.a <- function(x) {
y <- 5 # update y from generic here
NextMethod()
}
Run Code Online (Sandbox Code Playgroud)
这直接跳转到默认方法时有效:
g(structure(.Data = 1, class = "c")) # here y is never updated
# x y
# 1 10
Run Code Online (Sandbox Code Playgroud)
但是当我经历时NextMethod(),y神秘地消失了:
g(structure(.Data = 1, class = "a")) # here y is updated, but cannot be …Run Code Online (Sandbox Code Playgroud) 在Ruby中,假设我有一个类Foo允许我对我的大量Foos进行编目.所有Foos都是绿色和球形的,这是一个基本的自然法则,所以我定义了类方法如下:
class Foo
def self.colour
"green"
end
def self.is_spherical?
true
end
end
Run Code Online (Sandbox Code Playgroud)
这让我做到了
Foo.colour # "green"
Run Code Online (Sandbox Code Playgroud)
但不是
my_foo = Foo.new
my_foo.colour # Error!
Run Code Online (Sandbox Code Playgroud)
尽管事实上my_foo是明显的绿色.
显然,我可以定义一个colour调用的实例方法self.class.colour,但是如果我有很多这样的基本特征,那就很难实现.
我也可以通过定义method_missing为任何缺失的方法尝试类来做到这一点,但我不清楚这是我应该做的事情还是丑陋的黑客,或者如何安全地进行(特别是因为我实际上在ActiveRecord下在Rails中,我理解用method_missing做一些Clever Fun Stuff).
你会推荐什么?
我在课堂上有一些关于staticmethods的问题.我将首先举一个例子.
例一:
class Static:
def __init__(self, first, last):
self.first = first
self.last = last
self.age = randint(0, 50)
def printName(self):
return self.first + self.last
@staticmethod
def printInfo():
return "Hello %s, your age is %s" % (self.first + self.last, self.age)
x = Static("Ephexeve", "M").printInfo()
Run Code Online (Sandbox Code Playgroud)
输出:
Traceback (most recent call last):
File "/home/ephexeve/Workspace/Tests/classestest.py", line 90, in <module>
x = Static("Ephexeve", "M").printInfo()
File "/home/ephexeve/Workspace/Tests/classestest.py", line 88, in printInfo
return "Hello %s, your age is %s" % (self.first + self.last, self.age)
NameError: …Run Code Online (Sandbox Code Playgroud) 我想声明Python类中的一个类方法调用另一个带有一组参数的classmethod.我希望模拟的classmethod是"spec-ed",因此它会检测是否使用错误的参数调用它.
当我使用patch.object(.., autospec=True, ..)classmethod 补丁时,classmethod被替换为a NonCallableMagicMock并在我尝试调用它时引发错误.
from mock import patch
class A(object):
@classmethod
def api_meth(cls):
return cls._internal_classmethod(1, 2, 3)
@classmethod
def _internal_classmethod(cls, n, m, o):
return sum(n, m, o)
with patch.object(A, '_internal_classmethod') as p:
print(type(p).__name__)
with patch.object(A, '_internal_classmethod', autospec=True) as p:
print(type(p).__name__)
Run Code Online (Sandbox Code Playgroud)
产生输出:
MagicMock
NonCallableMagicMock
Run Code Online (Sandbox Code Playgroud)
我怎样才能得到一个特定的模拟器来判断_internal_classmethod它所属的类何时不被嘲笑?
class-method ×10
python ×5
ruby ×4
oop ×3
class ×2
decorator ×2
inheritance ×2
attributes ×1
constants ×1
dynamic ×1
eigenclass ×1
metaclass ×1
mocking ×1
module ×1
overriding ×1
python-mock ×1
r ×1