标签: dynamic-dispatch

如何使用Python @singledispatch 注册typing.Callable?

背景

假设我要实现一个简单的装饰器@notifyme,在调用装饰函数时打印一条消息。我希望装饰器接受一个参数来打印定制消息;参数(以及参数周围的括号)可以省略,在这种情况下将打印默认消息:

@notifyme('Foo is invoked!')
def foo():
    pass

@notifyme  # instead of @notifyme()
def bar():
    pass
Run Code Online (Sandbox Code Playgroud)

为了允许省略括号,我必须提供以下两种实现@notifyme

  1. 第一个实现允许用户自定义消息,因此它接受一个字符串作为参数并返回一个装饰器:

    def notifyme_customized(message: str) -> Callable[[Callable], Callable]:
        def decorator(func: Callable) -> Callable:
            def decorated_func(*args, **kwargs):
                print(str)
                return func(*args, **kwargs)
            return decorated_func
        return decorator
    
    Run Code Online (Sandbox Code Playgroud)
  2. 第二个实现本身是一个装饰器,并使用第一个实现来打印默认消息:

    def notifyme_default(func: Callable) -> Callable:
        return notifyme_customized('The function is invoked.')(func)
    
    Run Code Online (Sandbox Code Playgroud)

为了使上面的两个实现使用相同的名称notifyme,我曾经functools.singledispatch动态地将调用分派notifyme到两个实现之一:

# This is a complete minimal reproducible example

from functools import singledispatch
from typing import Callable …
Run Code Online (Sandbox Code Playgroud)

python callable dynamic-dispatch python-3.8

8
推荐指数
2
解决办法
2411
查看次数

使用虚方法表在C中动态调度

我希望在C中实现动态调度的提示(最好通过一个很好的例子).

我正在学习C并且作为练习,我想使用动态调度虚拟方法表从Java转换为C.

例如我有一个java代码:

abstract class Foo {
    public abstract int val(); 
    public abstract Boolean error();
}

class Fail extends Foo {
    public int val(){ return 0;}
    public Boolean error(){return true;}
}

class IntFoo extends Foo {
    int v;
    public IntFoo(int value){this.value=v;}
    public int val(){ return v;}
    public Boolean error(){return False;}
}
Run Code Online (Sandbox Code Playgroud)

我可以翻译一些像这样的基本内容:

typedef struct Foo{
    void(**vtable);
}Foo;

typedef struct Fail{
    void(**vtable);
    struct Foo inherited;
}Fail;

typedef struct IntFoo{
    void(**vtable);
    struct Foo inherited;
}IntFoo;
Run Code Online (Sandbox Code Playgroud)

我在试图完成这个时遇到困难,因为我不知道:

  1. 如何在c中定义这些方法.
  2. 设置这些方法的地址,vtable以便编译器识别正确的调用方法.
  3. 还有什么可以让它发挥作用.

c java polymorphism vtable dynamic-dispatch

7
推荐指数
2
解决办法
1160
查看次数

Java中的Binding和Dispatching有什么区别?

关联名称太多:早期和晚期绑定,静态和动态调度,运行时与编译时多态等等,我不明白其中的区别.

我找到了明确的解释,但这是正确的吗?我会解释JustinC:

绑定:是确定变量的类型(对象?).如果它在编译时完成,它的早期绑定.如果它是在运行时完成的,那就是后期绑定.

Dispatch:确定哪个方法与方法调用匹配.Static Dispatch是编译时的计算方法,而动态调度是在运行时执行的.

绑定是否将原始值和引用变量分别与原始值和对象进行匹配?

编辑:请给我一些明确的参考资料,以便我可以阅读更多相关信息.

java late-binding dynamic-dispatch early-binding static-dispatch

7
推荐指数
1
解决办法
837
查看次数

动态调度的 &dyn Trait 和 Box<dyn Trait> 有什么区别?

使用不同的模式运行new_foo1new_foo2返回相同的特征Foonew_foo1除了更冗长之外,我没有看到它们之间有任何功能差异。两者之间有优选的方式吗?这两种模式有什么微妙的影响吗?

trait Foo {
    fn bar(&self);
}

struct FooIm {}

impl Foo for FooIm {
    fn bar(&self) {
        println!("bar from FooIm")
    }
}

fn new_foo1<'a>() -> &'a (dyn Foo + 'a) {
    &FooIm {}
}

fn new_foo2() -> Box<dyn Foo> {
    let f = FooIm {};
    Box::new(f)
}

fn main() {
    let f1 = new_foo1();
    let f2 = new_foo2();

    f1.bar();
    f2.bar();
}
Run Code Online (Sandbox Code Playgroud)

dynamic-dispatch rust

7
推荐指数
0
解决办法
5735
查看次数

在Java中神奇地调用方法

有没有像在PHP中那样在Java中使用魔术方法的方法__call

例如:

 class foo {
     @Setter @Getter
     int id;

     @Getter
     Map <String, ClassInFoo> myMap;

     protected class ClassInFoo {
          @Setter @Getter
          String name;
     }

     @Setter
     String defaultKey;
 }
Run Code Online (Sandbox Code Playgroud)

我正在使用Project Lombok注释来获取getter和setter方法来简化代码.

让我们考虑我的地图包含由String映射的几个项目,defaultKey定义默认项目.

我想要的是能够调用foo.getName()哪个会返回默认名称foo.myMap.get(defaultKey).getName().

我不能手动编写所有getter的原因是Foo类实际上是继承了泛型,而内部类可能是不同的.

我有点需要:

   function Object __call(method) {
           if (exist_method(this.method)
                return this.method();
           else 
                return this.myMap.get(defaultKey).method();
   }
Run Code Online (Sandbox Code Playgroud)

这在Java中是否可行?

编辑:

我做了一个更精确的例子,说明我想在这里实现的目标:https://gist.github.com/1864457

这样做的唯一原因是"简写"内部类中的方法.

java dynamic-dispatch lombok

6
推荐指数
1
解决办法
4643
查看次数

编码许多小方法是否会对Objective-C产生性能影响?

我来自Ruby,并且采用了单一责任原则,封装,松耦合,小可测试方法等方法,因此我的代码往往会频繁地从一个方法跳到另一个方法.这就是我习惯在Ruby世界中工作的方式.我认为这是最好的工作方式,主要用于BDD,因为一旦你开始使用"大"方法做多件事,测试变得非常困难.

我想知道这种方法是否有任何缺点,只要性能有显着差异?

performance objective-c dynamic-dispatch

6
推荐指数
1
解决办法
272
查看次数

Python中的函数模式/谓词匹配

我希望能够分派函数的不同实现,不仅基于第一个参数的类型,而且基于任意谓词.目前我必须这样做:

def f(param):
    try:
        if param > 0:
            # do something
    except TypeError:
        pass
    try:
        if all(isinstance(item, str) for item in param):
            # do something else
    except TypeError:
        raise TypeError('Illegal input.')
Run Code Online (Sandbox Code Playgroud)

这是我希望能够做到的精神:

@generic
def f(param):
    raise TypeError('Illegal input.')  # default

@f.when(lambda param: param > 0)
def f_when_param_positive(param):
    # do something

@f.when(lambda param: all(isinstance(item, str) for item in param))
def f_when_param_iterable_of_strings(param):
    # do something else
Run Code Online (Sandbox Code Playgroud)

它类似于Python 3 singledispatch,但singledispatch只支持对类型的调度,而不支持任意谓词.

TL; DR:是否有一个库允许基于任意谓词(不仅是参数的类型)的基于谓词的函数调度?

python dynamic-dispatch libraries

6
推荐指数
1
解决办法
612
查看次数

当`dyn`与绝对路径一起使用时出错[E0433]

我正在玩dynRust 1.27中引入的特性,并且偶然发现了这个编译错误:

error[E0433]: failed to resolve. Use of undeclared type or module `dyn`
 --> src\main.rs:1:30
  |
1 | fn _run0() -> Result<(), Box<dyn ::std::error::Error>> { Ok(()) }
  |                              ^^^ Use of undeclared type or module `dyn`
Run Code Online (Sandbox Code Playgroud)

所有其他变种编译正常:

fn _run0() -> Result<(), Box<dyn ::std::error::Error>> { Ok(()) } // Error

fn _run1() -> Result<(), Box<dyn std::error::Error>> { Ok(()) } // Ok

fn _run2() -> Result<(), Box<::std::error::Error>> { Ok(()) } // Ok
Run Code Online (Sandbox Code Playgroud)

这是打算行为吗?


rustc 1.27.0(3eda71b00 2018-06-19)

dynamic-dispatch language-lawyer rust

6
推荐指数
1
解决办法
207
查看次数

为什么C++不允许您请求指向最派生类的指针?

(这个问题应该通过对Stroustrup的引用来回答.)

能够请求指向最派生类的指针似乎非常有用,如下所示:

class Base { ... };
class DerivedA { ... };
class DerivedB { ... };
class Processor
{
  public:
  void Do(Base* b) {...}
  void Do(DerivedA* d) {...}
  void Do(DerivedB* d) {...}
};

list<Base*> things;
Processor p;
for(list<Base*>::iterator i=things.begin(), e=things.end(); i!=e; ++i)
{
    p.Do(CAST_TO_MOST_DERIVED_CLASS(*i));
}
Run Code Online (Sandbox Code Playgroud)

但是c ++中没有提供这种机制.为什么?

更新,激励示例:

假设您没有Base和Derived and Processor,而是拥有:

class Fruit
class Apple : public Fruit
class Orange: public Fruit

class Eater
{
   void Eat(Fruit* f)  { ... }
   void Eat(Apple* f)  { Wash(f); ... }
   void …
Run Code Online (Sandbox Code Playgroud)

c++ inheritance multiple-dispatch rtti dynamic-dispatch

5
推荐指数
4
解决办法
588
查看次数

Fragile Base Class是"继承打破封装"的唯一原因吗?

正如"四人帮"在" 设计模式 "中所述:" 人们经常说 '继承打破了封装'",在"面向对象编程语言中的封装和继承"中解释Snyder.

然而,每次我读" 继承断裂包封 ",这要求背后的原因要么依稀解释的,或与所述的一个例子说明脆基类的问题.

在阅读论文时,我感觉真正打破封装的唯一继承属性是downcalls,这是开放递归(动态调度打开this)允许的特性,并定义为"当超类方法调用在子类中重写的方法时",根据Ruby&Leavens在"安全地创建正确的子类而不看超类代码"中的说法.
此外,根据Aldrich在"选择性开放递归:脆弱基类问题的解决方案"中的说法,开放递归显然是导致脆弱基类问题的原因.

因此,如果脆弱基类问题是"继承打破封装"的唯一原因,那么可以更清楚地说,下调会破坏封装.由于存在一些解决方案以避免在使用继承时进行下调,因此继承本身并不真正涉及破坏封装.此外,四人帮提出的取消继承的委托模式也可以允许开放递归和下调,因为委托人的context(this)由委托使用(这可能导致一种脆弱的委托类问题).

因此,我的问题是:
脆弱的基类问题是否被称为"继承打破封装"的唯一原因?

oop inheritance encapsulation late-binding dynamic-dispatch

5
推荐指数
2
解决办法
427
查看次数