You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python如何编写函数根据传入参数动态生成指定类的实例

问题描述

我是Python新手,正尝试编写一个函数,能够返回三个候选类中某一个类的实例,且将函数的传入参数作为实例的属性。
原始代码如下:

class User:
    def __init__(self, nick, full_name, reg_date, age, role):
        self.nick = nick
        self.full_name = full_name 
        self.reg_date = reg_date
        self.age = age
        self.role = role

class Staff(User):
    def __init__(self, nick, full_name, reg_date, age, role):
        super().__init__(nick, full_name, reg_date, age, role)


class Adult(Staff):
    def __init__(self, nick, full_name, reg_date, age, role):
        super().__init__(nick, full_name, reg_date, age, role)

class Young(Adult):
    def __init__(self,nick, full_name, reg_date, age, role):
        super().__init__(full_name, nick, reg_date, age, role)



def sign_up(nick, full_name, reg_date, age, role):
    nick = (input('Choose a nickname: '))
    full_name = (input('Please, introduce your name: '))
    reg_date = str(date.today())
    age = (input('Please, introduce your age: '))
    role = (input('Please, introduce your role (Staff, Adult or Young)'))
    valid_roles = ['Staff', 'Adult', 'Young']
    exec('nick = role(full_name, reg_date, age, role)

预期目标:运行sign_up函数时,用户输入的nick参数值将作为实例的变量名,输入的role参数对应实例所属的类,其余参数作为实例的初始化属性。
例如调用:

sign_in('nick1', 'John Doe', reg_date, 38, 'Staff')

应当得到如下等价执行结果:

nick1 = Staff(full_name, reg_date, age)
存在的问题
  • 用exec动态创建全局变量是非常差的实践,可维护性极低,还存在任意代码执行的安全风险,这类需求应该用字典做键值映射实现。
  • Young类的__init__调用父类构造时,把nick和full_name的传参顺序写反了,会导致实例属性赋值错误。
  • 函数定义了形参,但内部直接用input的返回值覆盖了所有形参,外部传入的参数完全不生效。
  • role获取到的是用户输入的字符串,不是类对象,不能直接加括号当构造函数调用。
  • 输入的age是字符串类型,后续如果做年龄相关的逻辑判断会报错,需要转成整数。
  • 最后一行exec的参数字符串没有闭合,存在语法错误。
  • 没有做输入合法性校验,用户输入非法角色、非法年龄时代码会直接崩溃。
修正方案

用字典维护「角色名-对应类」的映射,再用另一个字典存储「昵称-用户实例」的键值对,完全替代动态创建变量的方案,同时补全输入校验、修复参数顺序错误:

from datetime import date

class User:
    def __init__(self, nick, full_name, reg_date, age, role):
        self.nick = nick
        self.full_name = full_name 
        self.reg_date = reg_date
        self.age = age
        self.role = role

# 子类如果没有额外的初始化逻辑,不需要重复写__init__,直接继承父类实现即可
class Staff(User):
    pass

class Adult(Staff):
    pass

class Young(Adult):
    pass

# 角色字符串和类的映射表
ROLE_CLASS_MAP = {
    'Staff': Staff,
    'Adult': Adult,
    'Young': Young
}

# 存储所有注册用户,键为昵称,值为对应的类实例
user_registry = {}

def sign_up():
    # 收集用户输入,做合法性校验
    nick = input('Choose a nickname: ').strip()
    while nick in user_registry:
        nick = input('Nickname already exists, please input another: ').strip()
    
    full_name = input('Please, introduce your name: ').strip()
    reg_date = str(date.today())

    while True:
        age_input = input('Please, introduce your age: ').strip()
        if age_input.isdigit() and 0 < int(age_input) < 120:
            age = int(age_input)
            break
        print("Please input a valid age (integer between 1 and 119)")
    
    while True:
        role = input('Please, introduce your role (Staff, Adult or Young): ').strip()
        if role in ROLE_CLASS_MAP:
            break
        print(f"Invalid role, please choose from {list(ROLE_CLASS_MAP.keys())}")
    
    # 创建对应类的实例
    target_class = ROLE_CLASS_MAP[role]
    new_user = target_class(nick, full_name, reg_date, age, role)
    # 存入注册表,后续通过昵称即可取到实例
    user_registry[nick] = new_user
    print(f"Register success, welcome {nick}")
    return new_user
使用方式

调用sign_up()完成注册流程后,直接通过user_registry['你的昵称']就能拿到对应的实例,比如注册时输入昵称为nick1、角色选Staff,user_registry['nick1']就是你需要的Staff类实例,和你预期的动态创建nick1变量效果完全一致,且更安全、更容易维护。

补充:如果子类后续要加独有的属性/方法,再重写__init__即可,不需要写和父类完全一致的初始化逻辑重复调用super,减少冗余代码。

内容的提问来源于stack exchange,提问作者Arochal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 15:12:46