在Python中,如何使函数接受嵌入在字符串中的变量序列?

时间:2022-06-30 15:29:24

In Python:

在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])

Can the string a be 'transformed' so that the function sees the variables? Thank you.

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

Later update: Thank you for answering my question. I am including the bigger problem and why I had to resort to the eval function (not desired according to your answers). The function:

稍后更新:感谢您回答我的问题。我包括更大的问题以及为什么我不得不求助于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

According to your answers, there are better ways of solving this..

根据你的答案,有更好的方法来解决这个问题。

3 个解决方案

#1


3  

To do this, you can combine the eval function to evaluate the string with the * operator to apply my_function on the resulting tuple:

为此,您可以组合eval函数以使用*运算符计算字符串,以在生成的元组上应用my_function:

my_function(*eval(a))

However, doing this without a very good reason is almost always an indication of bad design. eval makes your code vulnerable to run-time errors and code injection attacks, and removes important performance optimizations. If you describe your actual requirements, it is likely that someone can propose a better solution.

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

#2


3  

You had an XY problem.
Your real X problem was to pass an arbitrary number of objects to a function.
After having defined a string containing the identifiers of these objects, the Y solution to extract back the objects from this string became your graal.
But I'm pretty sure that the following snippet answers to your real X problem:

你有一个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)

It's a facility offered by Python to pass arbitrary number of arguments to a function, not present in all programming languages. Would be a pity to complicate one's life , not using it.

它是Python提供的一种工具,可以将任意数量的参数传递给函数,而不是所有编程语言都存在。将一个人的生活复杂化而不是使用它会是一种遗憾。

I think that new members should be informed, or even prevented, not to upvote and accept answers too rapidly.

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

EDIT

I think that you can replace the code block in your question with this one:

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

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])   

You could even define Point() in such a way that it would accept a couple (tuple, list... , I dont't know what your pts are) instead of elements of pt
So, you could write Point(x) instead of Point(*x) and

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

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

instead of

代替

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

but would need to write Point((v.x,v.y)) instead of Point(v.x,v.y)

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

#3


2  

Python methods take arbitrary argument lists. What this means is that your function can take any number of arguments.

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

Here is an example:

这是一个例子:

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

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

Now, suppose you wanted to pass a list with values in it as arguments:

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

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

Now this will result in:

现在这将导致:

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

A tuple with your list as the first argument. What we want is the same affect as foo('a','b','c','d'). To get that, we need to expand the list, like this:

以列表作为第一个参数的元组。我们想要的是与foo相同的影响('a','b','c','d')。为此,我们需要扩展列表,如下所示:

foo(*mylist)

Now you'll get the same result:

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

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

Taking this and applying it to your problem:

考虑到这一点并将其应用于您的问题:

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

#1


3  

To do this, you can combine the eval function to evaluate the string with the * operator to apply my_function on the resulting tuple:

为此,您可以组合eval函数以使用*运算符计算字符串,以在生成的元组上应用my_function:

my_function(*eval(a))

However, doing this without a very good reason is almost always an indication of bad design. eval makes your code vulnerable to run-time errors and code injection attacks, and removes important performance optimizations. If you describe your actual requirements, it is likely that someone can propose a better solution.

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

#2


3  

You had an XY problem.
Your real X problem was to pass an arbitrary number of objects to a function.
After having defined a string containing the identifiers of these objects, the Y solution to extract back the objects from this string became your graal.
But I'm pretty sure that the following snippet answers to your real X problem:

你有一个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)

It's a facility offered by Python to pass arbitrary number of arguments to a function, not present in all programming languages. Would be a pity to complicate one's life , not using it.

它是Python提供的一种工具,可以将任意数量的参数传递给函数,而不是所有编程语言都存在。将一个人的生活复杂化而不是使用它会是一种遗憾。

I think that new members should be informed, or even prevented, not to upvote and accept answers too rapidly.

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

EDIT

I think that you can replace the code block in your question with this one:

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

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])   

You could even define Point() in such a way that it would accept a couple (tuple, list... , I dont't know what your pts are) instead of elements of pt
So, you could write Point(x) instead of Point(*x) and

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

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

instead of

代替

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

but would need to write Point((v.x,v.y)) instead of Point(v.x,v.y)

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

#3


2  

Python methods take arbitrary argument lists. What this means is that your function can take any number of arguments.

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

Here is an example:

这是一个例子:

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

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

Now, suppose you wanted to pass a list with values in it as arguments:

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

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

Now this will result in:

现在这将导致:

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

A tuple with your list as the first argument. What we want is the same affect as foo('a','b','c','d'). To get that, we need to expand the list, like this:

以列表作为第一个参数的元组。我们想要的是与foo相同的影响('a','b','c','d')。为此,我们需要扩展列表,如下所示:

foo(*mylist)

Now you'll get the same result:

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

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

Taking this and applying it to your problem:

考虑到这一点并将其应用于您的问题:

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