Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/276.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 如何递归转换类实例的属性_Python - Fatal编程技术网

Python 如何递归转换类实例的属性

Python 如何递归转换类实例的属性,python,Python,我有一门课: class Foo(object): def __init__(self, coord_tpl, coord_list, coord_dict, blah): # a single coord tuple # e.g. ((1, 2), (11, 22)) self.coord_tpl = coord_tpl # a list of coord tuple # e.g. [((1, 2),

我有一门课:

class Foo(object):
    def __init__(self, coord_tpl, coord_list, coord_dict, blah):
        # a single coord tuple
        # e.g. ((1, 2), (11, 22))
        self.coord_tpl = coord_tpl  

        # a list of coord tuple
        # e.g. [((1, 2), (11, 22)), ((3, 4), (33, 44))]
        self.coord_list = coord_list

        # a dict, whose value is a list of coord tuple
        # e.g. { 0: [((1, 2), (11, 22)), ((3, 4), (33, 44))],
        #        1: [((5, 6), (55, 66)), ((7, 8), (77, 88))] }
        self.coord_dict = coord_dict

        # some non-coord attributes
        self.blah = blah
我还有一个轴翻译功能:
coord\u translate

def coord_translate(old_coord):
    # apply some translation logic to old_coord (x_o, y_o)
    new_coord = ...
    return new_coord
问题

我有一个Foo实例Foo:

foo = Foo(...)
如何翻译坐标属性(
foo.coord\u tpl
foo.coord\u list
foo.coord\u dict
),而其他属性(
foo.blah
)保持不变,使用
coord\u translate
,以更优雅的方式,而不是递归地手工制作翻译逻辑

更新 确实存在以属性形式存在的递归结构:首先是简单的坐标元组,然后是坐标元组列表,最后是坐标元组列表

要执行转换逻辑,我可以递归地反映每个属性的类型,并应用
coord_translate

for k, v in foo.__dict__.items():
     if isinstance(v, tuple):
         setattr(foo, k, (coord_translate(v[0]), coord_translate(v[1])))
     elif isinstance(v, list):
         for c in v:
              ...
     elif isinstance(v, dict):
         ... 

我想知道是否还有其他一些策略可以做到这一点,而不是使用像
if-isinstace(…)…elif-isinstace(…)。。。其他的
你可以用try,但据我所知

a) 不良风格

b) 不比您当前的解决方案好

def coord_translate(self, input):
        try:
            coord_translate_dict(input)
        except ValueError:
            coord_translate_list(input)

在我看来,最干净的解决方案是使用单一数据类型,并将每个输入转换为与此类型匹配的数据类型——我非常确定已经有库来处理此问题

另一种方法是这样的:

    def coord_translate_dict(self, dict):
        # apply some translation logic
        try:
            # do your stuff
            return True
        except:
            return False

    def coord_translate_list(self, list):
        # apply some translation logic
        try:
            # do your stuff
            return True
        except:
            return False

    def coord_translate_tuple(self, tuple):
        # apply some translation logic
        try:
            # do your stuff
            return True
        except:
            return False

    def coord_translate(self, input):
        if not coord_translate_dict(input) and not coord_translate_list(input):
            coord_translate_tuple(input)

在C++等许多其他语言中,你可以重载函数(定义3个函数,命名为COODRION EXTION,但每个函数接受不同的数据类型) 因为python是一种强类型的动态语言,我不知道有什么方法可以做到这一点

你可以用try,但据我所知

a) 不良风格

b) 不比您当前的解决方案好

def coord_translate(self, input):
        try:
            coord_translate_dict(input)
        except ValueError:
            coord_translate_list(input)

在我看来,最干净的解决方案是使用单一数据类型,并将每个输入转换为与此类型匹配的数据类型——我非常确定已经有库来处理此问题

另一种方法是这样的:

    def coord_translate_dict(self, dict):
        # apply some translation logic
        try:
            # do your stuff
            return True
        except:
            return False

    def coord_translate_list(self, list):
        # apply some translation logic
        try:
            # do your stuff
            return True
        except:
            return False

    def coord_translate_tuple(self, tuple):
        # apply some translation logic
        try:
            # do your stuff
            return True
        except:
            return False

    def coord_translate(self, input):
        if not coord_translate_dict(input) and not coord_translate_list(input):
            coord_translate_tuple(input)
您可以尝试:

from abc import ABC, abstractmethod
from collections import defaultdict

class CoordType(ABC):
    registry_by_instance = defaultdict(list)

    @abstractmethod
    def coord_translate(self):
        pass

    @classmethod
    def apply_coord_translate(cls, instance):
        for attr in cls.registry_by_instance(instance):
            attr.coord_translate()

class CoordTpl(CoordType):
    def __init__(self, creation_instance, coord_tpl):
        self.coord_tpl = coord_tpl
        CoordType.registry_by_instance[creation_instance].append(self)

    def coord_translate(self):
        # your code to translate

class CoordList(CoordType):
    def __init__(self, creation_instance, coord_list):
        self.coord_list = coord_list
        CoordType.registry_by_instance[creation_instance].append(self)

    def coord_translate(self):
        # your code to translate

class CoordDict(CoordType):
    def __init__(self, creation_instance, coord_dict):
        self.coord_dict = coord_dict
        CoordType.registry_by_instance[creation_instance].append(self)

    def coord_translate(self):
        # your code to translate


class Foo(object):
    def __init__(self, coord_tpl, coord_list, coord_dict, blah):
        # a single coord tuple
        # e.g. ((1, 2), (11, 22))
        self.coord_tpl = CoordTpl(self.coord_tpl) 

        # a list of coord tuple
        # e.g. [((1, 2), (11, 22)), ((3, 4), (33, 44))]
        self.coord_list = CoordList(self, coord_list)

        # a dict, whose value is a list of coord tuple
        # e.g. { 0: [((1, 2), (11, 22)), ((3, 4), (33, 44))],
                 1: [((5, 6), (55, 66)), ((7, 8), (77, 88))] }
        self.coord_dict = CoordDict(self, coord_dict)

        # some non-coord attributes
        self.blah = blah

    def coord_translate(self):
        CoordType.coord_translate(self)
您可以尝试:

from abc import ABC, abstractmethod
from collections import defaultdict

class CoordType(ABC):
    registry_by_instance = defaultdict(list)

    @abstractmethod
    def coord_translate(self):
        pass

    @classmethod
    def apply_coord_translate(cls, instance):
        for attr in cls.registry_by_instance(instance):
            attr.coord_translate()

class CoordTpl(CoordType):
    def __init__(self, creation_instance, coord_tpl):
        self.coord_tpl = coord_tpl
        CoordType.registry_by_instance[creation_instance].append(self)

    def coord_translate(self):
        # your code to translate

class CoordList(CoordType):
    def __init__(self, creation_instance, coord_list):
        self.coord_list = coord_list
        CoordType.registry_by_instance[creation_instance].append(self)

    def coord_translate(self):
        # your code to translate

class CoordDict(CoordType):
    def __init__(self, creation_instance, coord_dict):
        self.coord_dict = coord_dict
        CoordType.registry_by_instance[creation_instance].append(self)

    def coord_translate(self):
        # your code to translate


class Foo(object):
    def __init__(self, coord_tpl, coord_list, coord_dict, blah):
        # a single coord tuple
        # e.g. ((1, 2), (11, 22))
        self.coord_tpl = CoordTpl(self.coord_tpl) 

        # a list of coord tuple
        # e.g. [((1, 2), (11, 22)), ((3, 4), (33, 44))]
        self.coord_list = CoordList(self, coord_list)

        # a dict, whose value is a list of coord tuple
        # e.g. { 0: [((1, 2), (11, 22)), ((3, 4), (33, 44))],
                 1: [((5, 6), (55, 66)), ((7, 8), (77, 88))] }
        self.coord_dict = CoordDict(self, coord_dict)

        # some non-coord attributes
        self.blah = blah

    def coord_translate(self):
        CoordType.coord_translate(self)

我个人避免类型转换和“属性魔法”(我被太多的bug咬了一口,并且盯着不可理解的间接指令看了太久),我更喜欢让一切尽可能明确和直接

我将定义几个辅助函数:

def coord_translate(old_coord):
    # Dummy implementation
    x,y = old_coord
    return (x+1, y+1)

def translate_tuple(tpl):
    return tuple(map(coord_translate, tpl))

def translate_list(ls):
    return list(map(translate_tuple, ls))

def translate_dict(dct):
    return dict([(k, translate_list(v)) for (k,v) in dct.items()])
然后写

def translate(self):
    self.coord_tpl = translate_tuple(self.coord_tpl)
    self.coord_list = translate_list(self.coord_list)
    self.coord_dict = translate_dict(self.coord_dict)

当然,如果愿意的话,您可以将这些助手函数包装在类型切换函数中。

我个人避免类型切换和“属性魔法”(我被太多的bug所困扰,并且盯着不可理解的间接指令看了太久),并且更喜欢尽可能地保持所有内容的明确和直接

我将定义几个辅助函数:

def coord_translate(old_coord):
    # Dummy implementation
    x,y = old_coord
    return (x+1, y+1)

def translate_tuple(tpl):
    return tuple(map(coord_translate, tpl))

def translate_list(ls):
    return list(map(translate_tuple, ls))

def translate_dict(dct):
    return dict([(k, translate_list(v)) for (k,v) in dct.items()])
然后写

def translate(self):
    self.coord_tpl = translate_tuple(self.coord_tpl)
    self.coord_list = translate_list(self.coord_list)
    self.coord_dict = translate_dict(self.coord_dict)

当然,如果愿意,您可以将这些助手函数包装到类型切换函数中。

轴平移是什么意思?你的意思是,翻译所有的x值,使它们是
x+dx
,例如。?你能添加你的类吗?否则就有点混乱了。@alkasm嗨,我用“轴平移”的定义更新了这个问题。我还不清楚这个平移。调用
coord\u translate
时,是否要修改属于
Foo
实例的所有坐标?请在代码中给出具体示例,说明
Foo
对象的外观,以及调用该方法后希望它的外观。明确显示最终结果应该是什么。coord_translate是你的类Foo的一部分吗?如果不是,这可能是您正在寻找的干净解决方案^^@rusu_ro1请参阅问题更新。谢谢。轴平移是什么意思?你的意思是,翻译所有的x值,使它们是
x+dx
,例如。?你能添加你的类吗?否则就有点混乱了。@alkasm嗨,我用“轴平移”的定义更新了这个问题。我还不清楚这个平移。调用
coord\u translate
时,是否要修改属于
Foo
实例的所有坐标?请在代码中给出具体示例,说明
Foo
对象的外观,以及调用该方法后希望它的外观。明确显示最终结果应该是什么。coord_translate是你的类Foo的一部分吗?如果不是,这可能是您正在寻找的干净解决方案^^@rusu_ro1请参阅问题更新。谢谢。谢谢,这个方法很容易适应我当前的代码。谢谢,这个方法很容易适应我当前的代码。谢谢你这么好的解决方案。我喜欢这个主意!谢谢你这么好的解决方案。我喜欢这个主意!