不要一开始就把争论压扁。当你写一个8元函数的时候
User
,你一定会犯错误,比如按错误的顺序传递论点。
以下哪项将生成您想要的用户?
-
User(24, "Jon Doe", "http://mywebsite.com", "I am an actor", "example@example.com", "M", "+12345678", "johndoe")
-
User(24, "Jon Doe", "http://mywebsite.com", "I am an actor", "example@example.com", "+12345678", "M", "johndoe")
不可能知道!如果函数采用描述符,则不存在此问题-
class User:
def __init__ (self, desc = {}):
self.desc = desc # whitelist items, if necessary
def __str__ (self):
# invent our own "destructuring" syntax
[ name, age, gender ] = \
destructure(self.desc, 'name', 'age', 'gender')
return f"{name} ({gender}) is {age} years old"
# create users with a "descriptor"
u = User({ 'age': 2, 'gender': 'M' })
v = User({ 'gender': 'F', 'age': 3 })
x = User({ 'gender': 'F', 'name': 'Alice', 'age': 4 })
print(u) # None (M) is 2 years old
print(v) # None (F) is 3 years old
print(x) # Alice (F) is 4 years old
我们可以定义自己的
destructure
AS -
def destructure (d, *keys):
return [ d[k] if k in d else None for k in keys ]
这仍然可能导致长链,但顺序取决于调用方,因此它不像原始问题中的8元函数那样脆弱-
[ name, age, gender ] = \
destructure(self.desc, 'name', 'age', 'gender')
# works the same as
[ gender, name, age ] = \
destructure(self.desc, 'gender', 'name', 'age')
另一种选择是使用关键字参数-
class User:
def __init__ (self, **desc):
self.desc = desc # whitelist items, if necessary
def __str__ (self):
[ name, age, gender ] = \
destructure(self.desc, 'name', 'age', 'gender')
return f"{name} ({gender}) is {age} years old"
# create users with keyword arguments
u = User(age = 2, gender = 'M')
v = User(gender = 'F', age = 3)
x = User(gender = 'F', name = 'Alice', age = 4)
print(u) # None (M) is 2 years old
print(v) # None (F) is 3 years old
print(x) # Alice (F) is 4 years old