Python混合位置与命名参数时args用法及Django批量创建指定属性超级用户
问题1:Python中混合位置参数、命名参数时怎么用*args
先搞清楚*args在函数调用时的核心作用:它能把列表/元组这类可迭代对象里的元素,挨个作为位置参数传入函数。当你需要同时传固定位置参数、展开*args,再加上命名参数(关键字参数)时,只要遵循「固定位置参数在前,*args次之,最后放关键字参数」的顺序就可以了。
举个实际的例子,假设你有这么个函数:
def calculate_total(base, tax, *extra_fees, discount): total = base + tax + sum(extra_fees) - discount return total
调用的时候,你可以这么混合使用:
# 先传固定位置参数,用*args展开额外费用列表,最后加折扣的关键字参数 total = calculate_total(100, 10, *[5, 3], discount=15) print(total) # 输出103
再比如,哪怕函数定义里没有*args,调用时也可以用*来展开部分位置参数,剩下的用关键字参数:
def send_message(to, subject, content): print(f"Sending to {to}: {subject} - {content}") # 用*展开前两个位置参数,第三个用关键字参数 send_message(*["alice@example.com", "Hello"], content="How are you?")
完全没问题,只要关键字参数放在*展开的内容后面就行——Python不允许*之后放位置参数,但关键字参数是合法的。
问题2:批量创建Django超级用户(带first_name这类命名参数)
看你给的单用户代码,create_superuser前两个是位置参数(邮箱、密码),first_name是关键字参数。要批量操作的话,有两种简单实用的方式:
方式1:用元组存储每个用户的参数,拆分位置和关键字
把每个用户的信息做成(邮箱, 密码, 名字)的元组,循环时拆包位置参数,再显式传递first_name:
# 构造批量用户数据 superuser_list = [ ('user1@gmail.com', 'pass123', 'UserOne'), ('user2@gmail.com', 'pass456', 'UserTwo'), # 可添加更多用户 ] # 循环创建用户 for email, pwd, fname in superuser_list: CustomUser.objects.create_superuser(email, pwd, first_name=fname)
方式2:全用关键字参数(更灵活易扩展)
其实create_superuser也支持用关键字参数传递邮箱和密码,所以可以把每个用户的信息写成字典,再用**把字典展开为关键字参数:
superuser_list = [ {'email': 'user1@gmail.com', 'password': 'pass123', 'first_name': 'UserOne'}, {'email': 'user2@gmail.com', 'password': 'pass456', 'first_name': 'UserTwo'}, # 可添加更多用户 ] # 批量创建(列表推导式或普通循环都可以) [CustomUser.objects.create_superuser(**user) for user in superuser_list]
这种方式的好处是,以后如果要添加其他参数(比如last_name),直接在字典里加键值对就行,不用修改循环逻辑,扩展性更强。
另外提个优化建议:如果要创建100个这种量级的用户,循环调用create_superuser会频繁操作数据库,效率较低。可以尝试用bulk_create,但注意bulk_create不会自动执行create_superuser里的逻辑(比如设置is_superuser=True、哈希密码等),需要手动处理:
from django.contrib.auth import get_user_model CustomUser = get_user_model() user_objects = [] for user_data in superuser_list: user = CustomUser( email=user_data['email'], first_name=user_data['first_name'], is_superuser=True, is_staff=True, is_active=True ) user.set_password(user_data['password']) # 手动哈希密码,bulk_create不会处理这一步 user_objects.append(user) CustomUser.objects.bulk_create(user_objects)
这种方式一次性插入所有用户,比循环调用单个创建接口效率高很多,适合大量用户的场景。
内容的提问来源于stack exchange,提问作者Amin Ba

