动态创建类型

2024-06-16 10:37:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我可以动态创建类定义,如下所示:

class_name = 'Human'
base_classes = (object,)
attributes = {'name':'',
              'books':list(),
              'say_hello':lambda self: sys.stdout.write('Hello!')}

Human = type(class_name, base_classes, attributes)

uzumaxy = Human()
uzumaxy.name = 'Maxim'
uzumaxy.books.append('Programming via .NET')
print(uzumaxy.name)  # Out: "Maxim"
print(uzumaxy.books) # Out: "['Programming via .NET']"

grandrey = Human()
grandrey.name = 'Andrey'
grandrey.books.append('Programming via python')

print(grandrey.name)  # Out: "Andrey"
print(uzumaxy.name)  # Out: "Maxim"

print(grandrey.books)  # Out: "['Programming via .NET', 'Programming via python']"
print(uzumaxy.books)  # Out: "['Programming via .NET', 'Programming via python']", but i'm expecting: "['Programming via .NET']"

似乎,属性“name”是实例级的,但为什么属性“books”是类级的呢? 如何使用实例级属性动态创建类型定义?谢谢你的帮助。你知道吗


Tags: namebasenet属性outbooksviaclass
2条回答

实际上,namebooks都是类级别的。只是字符串是不可变的,所以当您使用uzumaxy.name = "Maxim"时,您将添加一个名为name的新属性来隐藏类name,而对于uzumaxy.books.append("Programming via .NET"),您将访问现有的(类)books并对其进行修改。您的代码等效于:

class Human(object):
    name = ''
    books = []

    def say_hello(self):
        sys.stdout.write("Hello!")

注意同样的行为。传统上,我们会这样写Human来解决这个问题:

class Human(object):
    def __init__(self):
        self.name = ''
        self.books = []

    def say_hello(self):
        sys.stdout.write("Hello!")

现在每个实例都有自己的namebooks。要对动态创建的类型执行此操作,您可以执行基本相同的操作,给它一个__init__

def init_human(self):
    self.name = ''
    self.books = []

attributes = { '__init__': init_human,
               'say_hello': lambda self: sys.stdout.write("Hello!") }

他们都是同班同学。name是简单的不可变的,所以乍一看它不是类级别的。大多数修改它的尝试都会创建一个具有相同名称的新实例级属性。你知道吗

就像以常规方式编写类一样,您需要在构造函数中创建实例属性:

def __init__(self):
    self.name = ''
    self.books = []

def say_hello(self):
    # This prints a newline. The original didn't.
    print 'Hello!'

Human = type('Human', (object,), {
    '__init__': __init__,
    'say_hello': say_hello,
})

相关问题 更多 >