2

在 Python 中:

a = "l[0], l[1], l[2], l[3]"
# l[0] etc. have their own value

my_function(a) #doesn't work


#but this does work
my_function(l[0], l[1], l[2], l[3])

字符串 a 可以“转换”以便函数看到变量吗?谢谢你。

稍后更新:感谢您回答我的问题。我包括了更大的问题以及为什么我不得不求助于 eval 函数(根据您的答案,这不是所需的)。功能:

class Line(object):
def __init__(self, pt1, pt2, *pt):
    pt1 = Point(pt1[0],pt1[1])
    pt2 = Point(pt2[0],pt2[1])
    self.vertices = [pt1, pt2]
    for i in pt:
        self.vertices.append(Point(i[0],i[1]))

def __getitem__(self, key):
    pt = self.vertices[key]
    p = Point(p[0],p[1])
    return p

#Here is the part with the issue:

def move(self, dx, dy):
    pts = len(self.vertices)
    l = self.vertices

    pt1 = Point(Point(l[0].x, l[0].y).move(dx, dy).x, Point(l[0].x, l[0].y).move(dx, dy).y)
    pt2 = Point(Point(l[1].x, l[1].y).move(dx, dy).x, Point(l[1].x, l[1].y).move(dx, dy).y)
    if pts == 2:
        mv = LineString(p1, p2)
    if pts > 2:
        bla = ''
        for i in [2,pts]:
            px = Point(l[i].x, l[i].y).move(dx, dy).x
            py = Point(l[i].x, l[i].y).move(dx, dy).y
            l[i] = Point(px,py)
            bla += 'l[' + str(i) + '], '
            arguments = bla[:-2]
            mv = LineString(pt1, pt2, *eval(arguments))
    return mv

根据您的回答,有更好的方法来解决这个问题..

4

3 回答 3

3

为此,您可以将eval评估字符串的函数与*运算符结合起来,以应用于my_function结果元组:

my_function(*eval(a))

然而,在没有充分理由的情况下这样做几乎总是表明设计不佳。eval使您的代码容易受到运行时错误和代码注入攻击,并删除重要的性能优化。如果您描述您的实际需求,很可能有人可以提出更好的解决方案。

于 2013-03-03T09:51:31.233 回答
3

你有一个XY问题
您真正的X问题是将任意数量的对象传递给函数。
在定义了包含这些对象的标识符的字符串之后,从该字符串中提取对象的Y解决方案就成为了您的解决方案。
但我很确定以下代码片段回答了您真正的X问题:

    if pts > 2:
        blal = []
        for i in [2,pts]:
            px = Point(l[i].x, l[i].y).move(dx, dy).x
            py = Point(l[i].x, l[i].y).move(dx, dy).y
            blal.append(Point(px,py))
        mv = LineString(pt1, pt2, *blal)

它是 Python 提供的一种工具,用于将任意数量的参数传递给函数,并非在所有编程语言中都存在。把自己的生活复杂化,不使用它会很可惜。

我认为应该通知甚至阻止新成员不要过快地投票和接受答案。

编辑

我认为您可以用这个替换问题中的代码块:

from itertools import chain

class Line(object):
    def __init__(self, pt1, pt2, *pt):
        self.vertices = map(lambda x: Point(*x),
                            chain((pt1,pt2), pt))

    def __getitem__(self, key):
        return Point(*self.vertices[key])

    def move(self, dx, dy):
        return LineString(*[ Point(Point(v.x, v.y).move(dx, dy).x,
                                   Point(v.x, v.y).move(dx, dy).y)
                             for v in self.vertices])   

                           

你甚至可以定义Point()这样一种方式,它会接受一对(元组,列表......,我不知道你pt的 s 是什么)而不是 So 的元素pt
,你可以写Point(x)而不是Point(*x)and

self.vertices = map(Point, chain((pt1,pt2), pt))

代替

self.vertices = map(lambda x: Point(*x),
                    chain((pt1,pt2), pt))

但需要写Point((v.x,v.y))而不是 Point(v.x,v.y)

于 2013-03-04T00:08:36.643 回答
2

Python 方法采用任意参数列表。这意味着您的函数可以接受任意数量的参数。

这是一个例子:

def foo(*args, **kwargs):
   print args

foo('a','b','c','d')

现在,假设您想传递一个包含值的列表作为参数:

mylist = ['a','b','c','d']
foo(mylist)

现在这将导致:

(['a', 'b', 'c', 'd'],)

以您的列表作为第一个参数的元组。我们想要的是和 一样的效果foo('a','b','c','d')。为此,我们需要扩展列表,如下所示:

foo(*mylist)

现在你会得到同样的结果:

('a', 'b', 'c', 'd')

将此并将其应用于您的问题:

def foo(*args, **kwargs):
   print "Total arguments: {}".format(len(args))

v = "a, b, c"
>>> foo(v)
Total arguments: 1
>>> foo(*v.split(','))
Total arguments: 3
于 2013-03-03T09:52:34.133 回答