问题
Due to my current understanding of Python's syntax, I have run into an issue where I need to set a variable to a value but without using any operators. I have to use functions.
Consider this senario
class Senario:
x: str = ''
y: str = ''
set_global_variable(self, set_variable, val: str)
# some verification code and modifications
set_variable(val)
set_x(self, val: str)
self.set_global_variable(setX, val)
set_x(self, val: str)
self.set_global_variable(lambda new_x: self.x = new_x, val)
The benefit of setting variables like this is that adding a new variable doesn't require copying and pasting a bunch of verification code for the new setter method. It is more modular. The problem is that such a program doesn't run because lambdas can't use operators.
The error is self.set_global_variable(lambda new_x: self.x
--> =
<-- new_x, val)
It's not the proper syntax. In order to run a program like this, I need some sort of equals method that does the exact same thing as the = operator. The implementation would work as follows.
set_x(self, val: str)
self.set_global_variable(lambda new_x: self.x.equals(new_x), val)
Is there a built-in method in Python to do this, if only for strings? If not, can a method be easily written? One that can take a variable as input and set that exact variable to a new value, and not a local copy of it?
回答1:
The easiest solution may be to use a local function that performs the assignment, as follows:
def set_x(self, val: str):
def _set_variable(new_x):
self.x = new_x
self.set_global_variable(_set_variable, val)
However, if you want to use a lambda expression, you can try using the setattr built-in function of python, which does what you asked for:
def set_x(self, val: str):
self.set_global_variable(lambda new_x: setattr(self, "x", new_x), val)
A more general solution could be to pass the field name to the set_global_variable
and use setattr
to perform the assignment, as follows:
def set_global_variable(self, variable_name, val):
# some verification code and modifications
setattr(self, variable_name, val)
def set_x(self, val: str):
set_global_variable("x", val)
回答2:
So, you are using the term global
incorrectly, you are simply trying to dynamically set an attribute. This can be accomplished with setattr
, however, what you are actually trying to accomplish is to encapsulate setter logic. Python has the descriptor protocol. Here is how you would do something like this in Python:
class AlwaysCapitalized:
def __get__(self, instance, owner=None):
return getattr(instance, self.name)
def __set__(self, instance, value):
setattr(instance, self.name, value.capitalize())
def __set_name__(self, owner, name):
self.name = f"_{name}"
class MemberName:
first_name = AlwaysCapitalized()
last_name = AlwaysCapitalized()
def __init__(self, first, last):
self.first_name = first
self.last_name = last
name = MemberName("juan", "arrivillaga")
print(f"Hello, {name.first_name} {name.last_name}!")
Outputs:
Hello, Juan Arrivillaga!
Note, this can be re-used in various classes, and is very flexible if you want to modularize. And look how much cleaner the client code is, if you want to set an attribute with your logic, you just do self.attribute = value
, similarly, if you want to get an attribute, you just do self.attribute
. No ugly set_attribute()
and get_attribute()
all over the place
Note, property
objects are just descriptors, so are classmethod
and staticmethod
decorators. Actually, function objects are just descriptors, whose __get__
method essentially partially apply the instance as the first argument to itself.
See the Descriptor HOWTO
回答3:
You can use global
for this, like this:
def myfunc(x, y):
exec(f"global {x}”)
exec(f"{x} = {y}")
myfunc("x", "great")
print("Python is " + x)
However, I see that you are creating a setter that makes the property y
a global value, meaning you can only have 1 (meaningful) object op the type Scenario.
来源:https://stackoverflow.com/questions/63240924/is-there-a-function-in-python-that-does-the-same-thing-as-the-equals-operator