python - Ruby 中的装饰器(从 Python 迁移)

标签 python ruby decorator

我今天从 Python 的角度学习 Ruby。我完全没能解决的一件事是装饰器的等价物。为了精简内容,我尝试复制一个简单的 Python 装饰器:

#! /usr/bin/env python

import math

def document(f):
    def wrap(x):
        print "I am going to square", x
        f(x)
    return wrap

@document
def square(x):
    print math.pow(x, 2)

square(5)

运行这个给我:

I am going to square 5
25.0

因此,我想创建一个函数 square(x),但要对其进行装饰,以便它在执行之前提醒我它要对什么进行平方。让我们去掉糖以使其更基本:

...
def square(x):
    print math.pow(x, 2)
square = document(square)
...

那么,我该如何在 Ruby 中复制它呢?这是我的第一次尝试:

#! /usr/bin/env ruby

def document(f)
    def wrap(x)
        puts "I am going to square", x
        f(x)
        end
    return wrap
    end

def square(x)
    puts x**2
    end

square = document(square)

square(5)

运行此生成:

./ruby_decorate.rb:8:in `document': wrong number of arguments (0 for 1) (ArgumentError)
    from ./ruby_decorate.rb:15:in `<main>'

我猜这是因为圆括号不是强制性的,它把我的 return wrap 当作 return wrap() 的尝试。我知道没有办法在不调用函数的情况下引用它。

我已经尝试了其他各种方法,但没有什么能让我走得更远。

最佳答案

这是消除别名方法名称之间冲突问题的另一种方法(请注意,我使用模块进行装饰的其他解决方案也是一个不错的选择,因为它也避免了冲突):

module Documenter
    def document(func_name)   
        old_method = instance_method(func_name) 

        define_method(func_name) do |*args|   
            puts "about to call #{func_name}(#{args.join(', ')})"  
            old_method.bind(self).call(*args)  
        end
    end
end

上面的代码之所以有效,是因为 old_method 局部变量在新的“hello”方法中保持有效,因为 define_method block 是一个闭包。

关于python - Ruby 中的装饰器(从 Python 迁移),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1891429/

相关文章:

python - 如何在pandas中并排附加两个数据框列

python - 泛型、类和实例

ruby - 如何改进这种二分匹配解决方案?

python - Flask 中的自定义身份验证和参数检查

python - 素数检查Python

python - 在 Keras (tensorflow) 中合并多个模型

ruby - 你如何在 Jekyll 中按帖子计数对 site.tags 进行排序?

ruby - ruby 中的数据结构只存储唯一元素?

python 包装器函数在装饰器中接受参数

python - Python 2 中装饰子类中的 super()