Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python中的访问者模式 这是C++中访问者模式的一种简化实现。有可能在Python中实现类似的东西吗 我需要它,因为我将把对象从C++代码传递到Python中的函数。我的想法是用Python实现一个访问者,以找出对象的类型 我的C++代码: #include <iostream> #include <string> class t_element_base { public: virtual void accept( class t_visitor &v ) = 0; }; class t_element_deriv_one: public t_element_base { public: void accept( t_visitor &v ); std::string t_element_deriv_one_text() { return "t_element_deriv_one"; } }; class t_element_deriv_two: public t_element_base { public: void accept( t_visitor &v ); std::string t_element_deriv_two_text() { return "t_element_deriv_one"; } }; class t_visitor { public: void visit( t_element_deriv_one& e ){ std::cout << e.t_element_deriv_one_text() << std::endl; } void visit( t_element_deriv_two& e ){ std::cout << e.t_element_deriv_two_text() << std::endl; } }; void t_element_deriv_one::accept( t_visitor &v ) { v.visit( *this ); } void t_element_deriv_two::accept( t_visitor &v ) { v.visit( *this ); } int main ( void ) { t_element_base* list[] = { new t_element_deriv_one(), new t_element_deriv_two() }; t_visitor visitor; for( int i = 0; i < 2; i++ ) list[ i ]->accept( visitor ); } #包括 #包括 类t_元素_基 { 公众: 虚拟无效接受(t_类访问者&v)=0; }; 类t_元素_deriv_one:公共t_元素_base { 公众: 无效接受(t_访客和v); std::string t_element_deriv_one_text() { 返回“t_element_deriv_one”; } }; 第二类t_元素:公共t_元素基 { 公众: 无效接受(t_访客和v); std::string t_element_deriv_two_text() { 返回“t_element_deriv_one”; } }; t类访客 { 公众: voidvisit(t_element_derivu one&e){std::cout_Python_Visitor - Fatal编程技术网

python中的访问者模式 这是C++中访问者模式的一种简化实现。有可能在Python中实现类似的东西吗 我需要它,因为我将把对象从C++代码传递到Python中的函数。我的想法是用Python实现一个访问者,以找出对象的类型 我的C++代码: #include <iostream> #include <string> class t_element_base { public: virtual void accept( class t_visitor &v ) = 0; }; class t_element_deriv_one: public t_element_base { public: void accept( t_visitor &v ); std::string t_element_deriv_one_text() { return "t_element_deriv_one"; } }; class t_element_deriv_two: public t_element_base { public: void accept( t_visitor &v ); std::string t_element_deriv_two_text() { return "t_element_deriv_one"; } }; class t_visitor { public: void visit( t_element_deriv_one& e ){ std::cout << e.t_element_deriv_one_text() << std::endl; } void visit( t_element_deriv_two& e ){ std::cout << e.t_element_deriv_two_text() << std::endl; } }; void t_element_deriv_one::accept( t_visitor &v ) { v.visit( *this ); } void t_element_deriv_two::accept( t_visitor &v ) { v.visit( *this ); } int main ( void ) { t_element_base* list[] = { new t_element_deriv_one(), new t_element_deriv_two() }; t_visitor visitor; for( int i = 0; i < 2; i++ ) list[ i ]->accept( visitor ); } #包括 #包括 类t_元素_基 { 公众: 虚拟无效接受(t_类访问者&v)=0; }; 类t_元素_deriv_one:公共t_元素_base { 公众: 无效接受(t_访客和v); std::string t_element_deriv_one_text() { 返回“t_element_deriv_one”; } }; 第二类t_元素:公共t_元素基 { 公众: 无效接受(t_访客和v); std::string t_element_deriv_two_text() { 返回“t_element_deriv_one”; } }; t类访客 { 公众: voidvisit(t_element_derivu one&e){std::cout

python中的访问者模式 这是C++中访问者模式的一种简化实现。有可能在Python中实现类似的东西吗 我需要它,因为我将把对象从C++代码传递到Python中的函数。我的想法是用Python实现一个访问者,以找出对象的类型 我的C++代码: #include <iostream> #include <string> class t_element_base { public: virtual void accept( class t_visitor &v ) = 0; }; class t_element_deriv_one: public t_element_base { public: void accept( t_visitor &v ); std::string t_element_deriv_one_text() { return "t_element_deriv_one"; } }; class t_element_deriv_two: public t_element_base { public: void accept( t_visitor &v ); std::string t_element_deriv_two_text() { return "t_element_deriv_one"; } }; class t_visitor { public: void visit( t_element_deriv_one& e ){ std::cout << e.t_element_deriv_one_text() << std::endl; } void visit( t_element_deriv_two& e ){ std::cout << e.t_element_deriv_two_text() << std::endl; } }; void t_element_deriv_one::accept( t_visitor &v ) { v.visit( *this ); } void t_element_deriv_two::accept( t_visitor &v ) { v.visit( *this ); } int main ( void ) { t_element_base* list[] = { new t_element_deriv_one(), new t_element_deriv_two() }; t_visitor visitor; for( int i = 0; i < 2; i++ ) list[ i ]->accept( visitor ); } #包括 #包括 类t_元素_基 { 公众: 虚拟无效接受(t_类访问者&v)=0; }; 类t_元素_deriv_one:公共t_元素_base { 公众: 无效接受(t_访客和v); std::string t_element_deriv_one_text() { 返回“t_element_deriv_one”; } }; 第二类t_元素:公共t_元素基 { 公众: 无效接受(t_访客和v); std::string t_element_deriv_two_text() { 返回“t_element_deriv_one”; } }; t类访客 { 公众: voidvisit(t_element_derivu one&e){std::cout,python,visitor,Python,Visitor,您可以在Python中实现这一点,但实际上没有必要。Python是一种动态的解释语言,这意味着类型信息在运行时很容易获得 所以你上面的例子可以简单到 class C1(object): pass class C2(object): pass l = [C1(), C2()] if __name__=="__main__": for element in l: print type(element) 这将产生: <class '__main__.

您可以在Python中实现这一点,但实际上没有必要。Python是一种动态的解释语言,这意味着类型信息在运行时很容易获得

所以你上面的例子可以简单到

class C1(object):
    pass

class C2(object):
    pass

l = [C1(), C2()]
if __name__=="__main__":
    for element in l:
        print type(element)
这将产生:

<class '__main__.C1'>
<class '__main__.C2'>

访问者模式可以用Python实现,我使用它在我的数据和表示层之间实现一个干净的接口。数据层可以确定数据的顺序。表示层只需打印/格式化它:

在我的数据模块中,我有:

 class visited(object):
     ....
     def accept(self, visitor):
         visitor.visit(self)
         for child in self.children():
             child.accept(visitor)

 class typeA(visited):
    ....
我的所有数据类都继承自这个访问过的类,访问过的类还为我的所有对象所需的基本数据(例如名称、父对象等)公开了一些简单的函数,以及管理子列表的方法,子列表由
children()公开
上面使用的方法。每个子类都将构建自己的数据,拥有自己的属性,甚至可能有自己的子类-这些子类将添加到访问的超类维护的子类列表中

我的访客课是这样的:

class visitor(object):
      def __init__(self, obj_id):
          data_obj = _find_data_instance( obj_id )
          data_obj.accept(self)

      def visit( self, data_obj):
          if isinstance(data_obj, typeA):
               self.visit_typeA( dataobj)

      def visit_typeA(self, dataobj):
          """Formats the data for typeA"""
          ...

\u find\u data\u instance
是一些构建或查找我的一个数据实例实例的代码。在我的情况下,我的所有数据类都有一个构造函数,它接受一个
objectId
并返回,访问者对象知道要使用哪个数据类。

您可以使用decorator来获取所需的内容。从中复制一个示例:

以及@visitor装饰器的代码(以防链接失效):

相关博客(第一个似乎已经关闭):

编辑:

obj.\uuuuu qualname\uuuu
在Python 3.3之前不可用,因此我们必须对较低版本使用hack:-

def _qualname(obj):
    """Get the fully-qualified name of an object (including module)."""

    if hasattr(obj, '__qualname__'):
        qualname = obj.__qualname__
    else:
        qualname = str(obj).split(' ')[1]

    return obj.__module__ + '.' + qualname


不幸的是,上述解决方案不适用于3.3以下的python版本,因为方法在传递给装饰器时仍然是常规函数。您可以尝试同时使用类装饰器和方法装饰器,请参见。

如果有人认为它有用,我在python 2中使用内省获得了以下版本的
@visitor

_visitors = {}

def visitor(arg_type):
    "A @visitor decorator"
    def decorated(fn):
        import inspect
        stack = inspect.currentframe()
        class_name = stack.f_back.f_code.co_name
        full_name = fn.__module__ + '.' + class_name + '.' + fn.__name__
        _visitors[(full_name, arg_type)] = fn

        def _visitor_impl(self, arg, *rest, **kwargs):
            full_name = fn.__module__ + '.' + self.__class__.__name__ + '.' + fn.__name__
            assert (full_name, arg.__class__) in _visitors, "Can't find visitor in {} for {}".format(full_name, arg.__class__.__name__)
            method = _visitors[(full_name, arg.__class__)]
            return method(self, arg, *rest, **kwargs)

        return _visitor_impl

    return decorated
首先

  • 什么是面向对象编程?它是对单个参数的动态调度(java&C++中的隐式
    this
  • 访问者模式的作用是什么:它试图在这些语言上模拟双重分派,因此它使用两个类作为解决方法
在python中也可以采用同样的方法,但也可以使用decorator实现双重分派


感谢您的帮助。我不知道您使用的是哪一个Python版本,但在2.7.6版本中,
实例
调用不存在。您应该使用
isinstance
@Matthias-很好的捕获-如果您将其作为编辑建议,我会很高兴的谢谢您的帮助!我会接受您的答案,但Tony的答案有点错误我们很详细。
def _qualname(obj):
    """Get the fully-qualified name of an object (including module)."""

    if hasattr(obj, '__qualname__'):
        qualname = obj.__qualname__
    else:
        qualname = str(obj).split(' ')[1]

    return obj.__module__ + '.' + qualname
_visitors = {}

def visitor(arg_type):
    "A @visitor decorator"
    def decorated(fn):
        import inspect
        stack = inspect.currentframe()
        class_name = stack.f_back.f_code.co_name
        full_name = fn.__module__ + '.' + class_name + '.' + fn.__name__
        _visitors[(full_name, arg_type)] = fn

        def _visitor_impl(self, arg, *rest, **kwargs):
            full_name = fn.__module__ + '.' + self.__class__.__name__ + '.' + fn.__name__
            assert (full_name, arg.__class__) in _visitors, "Can't find visitor in {} for {}".format(full_name, arg.__class__.__name__)
            method = _visitors[(full_name, arg.__class__)]
            return method(self, arg, *rest, **kwargs)

        return _visitor_impl

    return decorated
class A: pass
class B: pass

class visitor:
    def __init__(self, f):
        self.f = f
        self.cases = {}

    def case(self, type1, type2):
        def call(fun):
            self.cases[(type1, type2)] = fun
        return call


    def __call__(self, arg1, arg2):
        fun = self.cases[type(arg1), type(arg2)]
        return fun(arg1, arg2)

@visitor
def f(x, y): pass


@f.case(A, int)
def fun1(a, b):
    print("called with A and int")


@f.case(B, str)
def fun2(a, b):
    print("called with B and string")



f(A(), 5)
f(B(), "hello")