[英]Can you assign variables in a lambda?
我正在使用lambda
語句來執行數學運算,並且碰巧重復使用了一個特定值。 因此,我想知道是否可以在lambda
語句中分配和使用變量。
我試過這樣的事情:
a = lambda n:(b=3+2*n) #[my math here]
然而,這只會引發錯誤,我想知道是否有辦法做到這一點。
不,你不能。 lambda
中只允許使用表達式:
lambda_expr ::= "lambda" [parameter_list]: expression lambda_expr_nocond ::= "lambda" [parameter_list]: expression_nocond
但是,您可以在lambda
中定義第二個lambda
,並立即使用您想要的參數調用它。 (這是否真的更好可能是另一個問題。)
>>> a = lambda n: ((3+2*n), n*(3+2*n)) # for reference, with repetition
>>> a(42)
(87, 3654)
>>> a2 = lambda n: (lambda b: (b, n*b))(3+2*n) # lambda inside lambda
>>> a2(42)
(87, 3654)
>>> a3 = lambda n: (lambda b=3+2*n: (b, n*b))() # using default parameter
>>> a3(42)
(87, 3654)
當然,外部和內部 lambda 都可以有多個參數,即您可以一次定義多個“變量”。 這種方法相對於例如在第一個之外定義第二個 lambda 的好處是,您仍然可以使用原始參數(如果您使用預先計算的b
調用a
則不可能)並且您必須為b
進行計算只有一次(除了重復調用一個函數來計算 a 中a
b
)。
此外,受鏈接問題的最佳答案的啟發,您還可以將一個或多個變量定義為 lambda 中列表理解或生成器的一部分,然后從該生成器或列表中獲取next
(第一個也是唯一一個)結果:
>>> a4 = lambda n: next((b, n*b) for b in [3+2*n])
>>> a4(42)
(87, 3654)
但是,我認為 lambda-in-a-lambda 背后的意圖更加清晰。 最后,請記住,除了單行lambda
,您還可以使用更清晰的三行def
語句...
此外,從 Python 3.8 開始,將會有賦值表達式,這應該可以編寫這樣的東西。 (使用 Python 3.8.10 測試。)
>>> a5 = lambda n: ((b := 3+2*n), n*b)
如果您使用 exec,您可以在 lambda 函數中分配變量:
>>> a = lambda: exec('global x; x = 1')
>>>a()
>>>x
1
如果您願意,您可以將您的 lambda 參數傳遞給另一個參數:
>>> b = lambda x: 3 + 2*x
>>> a = lambda y: y * b(y)
>>> a(1)
5
>>> a(2)
14
您可以創建 2 個不同的 lambda 函數並將一個傳遞給另一個。 例如,
b = lambda x: 3+2*x
a = lambda y: [my math here using variable b(y)]
我已經使用 PEP572 賦值表達式為 python 3.8+ 制作了這個配方來分配任意變量並執行任意表達式。
# python 3.8b1
lambda a: (
(bool(b:=a**2) or 1)
and (bool(c:=a-b) or 1)
and not print(f'compute: {a} + {b} + {c}')
and (
(ret:=a + b + c) or ret)
)
)
tst(0)
# prints: "compute: 0 + 0 + 0"; returns: 0
tst(1)
# prints: "compute: 1 + 1 + 0"; returns: 2
tst(8)
# prints: "compute: 8 + 64 + -56"; returns: 16
所以模式是:
lambda: [*vars]: (
(bool(a:=[expr(*vars)]) or 1)
and (bool([expr]) or 1)
and bool([always true expr])
and not bool([always false expr])
and (
# parentheses required so `result:=` doesn't capture the `or result` part
(result:=[result expr]) or result
)
)
如果您知道任何特定表達的真實性,這可能會被簡化。
話雖如此,如果您想分配一個變量以在 lambda 中重用,您可能應該考慮編寫一個普通函數。
我不是這方面的專家,但我這樣做的方式是像這樣修改globals()
或locals()
:
lambda: globals().__setitem__('some_variable', 'some value')
或者如果它在函數內部:
lambda: locals().__setitem__('some_variable', 'some value')
如果你願意,你也可以使用update()
而不是__setitem__()
,但這有點多余。
相反,您可以使用一些創造力,例如,如果您想對方程進行一些評估並將結果分配給變量,可以這樣做:
class Results:
res = 0
clas= Results()
setattr(clas, 'res', 3+2*4)
print(clas.res)
你可以用 oop 的方式重寫它,就像這樣,也許你無論如何都在使用 oop 結構,所以你可以將它集成到那里。
class example:
def __init__(self):
self.a = None
object = example()
a = lambda n:(setattr(object, "a", 3+2*n)) #[my math here]
a(2)
print(object.a)
輸出:
7
我希望4年后我遲到的答案會有用
Python 有setattr
函數來設置給定對象的屬性。 您可以在 lambda 表達式中使用它。
當您想以編程方式正確(抱歉)設置某個類或類的實例時, setattr
很有用。 它不經常使用,因為用=
表達式直接分配變量更容易。 但是對於 lambdas... 這是一種救贖。
此外,支持 settign 項的迭代(例如列表),您可以使用<iter>.__setitem__
。
x = lambda nameofvar, value: setattr(__builtins__, nameofvar, value)
# abc does not exist right now. Assigning and setting it to 10
x('abc', 10)
print(abc) # output: 10
alt ,如果要設置對象的屬性:
class MyClass:
my_attr = False
def __init__(self, value):
self.value = value
myinstance = MyClass(25)
x = lambda obj, nameofvar, value: setattr(obj, nameofvar, value)
short_x = lambda nameofvar, value: setattr(MyClass, nameofvar, value)
# ^^^ this one works only for MyClass' attributes.
print(MyClass.my_attr) # output: False
x(MyClass, 'my_attr', True) # Changing MyClass' my_attr's value
print(MyClass.my_attr) # output: True
x(MyClass, 'my_attr2', 5) # Assigning new attribute to MyClass
print(MyClass.my_attr2) # output: 5
short_x('my_attr2', 123) # Setting MyClass' my_attr2 to 123
print(MyClass.my_attr2) # output: 123
print(myinstance.value) # output: 25
x(myinstance, 'value', 500)
print(myinstance.value) # output: 500
class Value:
def __init__(self, value):
self.value = value
x = lambda var, newvalue: setattr(var, 'value', newvalue)
a = Value(15)
print(a.value) # output: 15
x(a, 25)
print(a.value) # output: 25
lst = [15, 30, 45, 60, 75, 90]
x = lambda iterable, item, value: iterable.__setitem__(item, value)
print(lst) # output: [15, 30, 45, 60, 75, 90]
x(lst, 2, 1000)
print(lst) # output: [15, 30, 1000, 60, 75, 90]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.