Фабрика классов для создания простых подобных структуре классов?

Системы основывались на платформах (.net, Java, и т.д.) решения. Правительство платит (охотно) за решение, но ROI намного выше, чем другие методы для получения того же результата.

правительство покупает много вещей, которые оно не делает интеллектуально собственный, потому что ему нужен продукт/решение. Миллионы примеров там.

11
задан martineau 31 August 2017 в 19:58
поделиться

6 ответов

Обновление варианта ThomasH:

def Struct(*args, **kwargs):
    def init(self, *iargs, **ikwargs):
        for k,v in kwargs.items():
            setattr(self, k, v)
        for i in range(len(iargs)):
            setattr(self, args[i], iargs[i])
        for k,v in ikwargs.items():
            setattr(self, k, v)

    name = kwargs.pop("name", "MyStruct")
    kwargs.update(dict((k, None) for k in args))
    return type(name, (object,), {'__init__': init, '__slots__': kwargs.keys()})

Это позволяет передавать параметры (и именованные параметры) в __ init __ () (без какой-либо проверки - кажется грубым):

>>> Person = Struct('fname', 'age')
>>> person1 = Person('Kevin', 25)
>>> person2 = Person(age=42, fname='Terry')
>>> person1.age += 10
>>> person2.age -= 10
>>> person1.fname, person1.age, person2.fname, person2.age
('Kevin', 35, 'Terry', 32)
>>> 

Обновление

Рассмотрим, как namedtuple () делает это в collections.py . Класс создается и расширяется как строка и оценивается. Также есть поддержка травления и т. Д.

2
ответ дан 3 December 2019 в 01:45
поделиться

Существует namedtuple

>>> from collections import namedtuple
>>> Person = namedtuple("Person", ("forename", "surname"))
>>> john = Person("John", "Doe")
>>> john.forename 
'John'
>>> john.surname 
'Doe'
1
ответ дан 3 December 2019 в 01:45
поделиться

Это продолжение ответа Cide (и, вероятно, интересно только тем, кто хочет копнуть глубже).

Я столкнулся с проблемой при использовании обновленного определения Cide для Struct (), использующего __slots__. Проблема в том, что экземпляры возвращаемых классов имеют атрибуты только для чтения:

>>> MS = Struct('forename','lastname')
>>> m=MS()
>>> m.forename='Jack'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'MyStruct' object attribute 'forename' is read-only

Похоже, что __slots__ блокирует атрибуты уровня экземпляра, когда есть атрибуты класса с одинаковыми именами. Я попытался преодолеть это, предоставив метод __init__, поэтому атрибуты экземпляра могут быть установлены во время создания объекта:

def Struct1(*args, **kwargs):
    def init(self):
        for k,v in kwargs.items():
            setattr(self, k, v)
    name = kwargs.pop("name", "MyStruct")
    kwargs.update(dict((k, None) for k in args))
    return type(name, (object,), {'__init__': init, '__slots__': kwargs.keys()})

В качестве общего эффекта сконструированный класс видит только метод __init__ и член __slots__, который работает должным образом:

>>> MS1 = Struct1('forename','lastname')
>>> m=MS1()
>>> m.forename='Jack'
>>> m.forename
'Jack'
3
ответ дан 3 December 2019 в 01:45
поделиться

Если вы используете Python 2.6, попробуйте класс стандартной библиотеки namedtuple .

>>> from collections import namedtuple
>>> Person = namedtuple('Person', ('forename', 'surname'))
>>> person1 = Person('John', 'Doe')
>>> person2 = Person(forename='Adam', surname='Monroe')
>>> person1.forename
'John'
>>> person2.surname
'Monroe'

Правка: Согласно комментариям, существует резервный порт для более ранних версий Python

16
ответ дан 3 December 2019 в 01:45
поделиться

Как и другие сказал, именованные кортежи в Python 2.6 / 3.x. В более старых версиях я обычно использую класс Stuff:

class Stuff(object):
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

john = Stuff(forename='John', surname='Doe')

Однако это не защищает вас от неправильного написания. Также есть рецепт для именованных кортежей в ActiveState:

http://code.activestate.com/recipes/500261/

5
ответ дан 3 December 2019 в 01:45
поделиться

Если вы используете python <2.6 или хотите расширить свой класс, чтобы делать больше, я бы предложил использовать встроенную функцию type () . Это имеет преимущество перед вашим решением в том, что установка __ dict __ происходит при создании класса, а не при создании экземпляра. Он также не определяет метод __ init __ и, следовательно, не приводит к странному поведению, если по какой-то причине класс снова вызывает __ init __ . Например:

def Struct(*args, **kwargs):
    name = kwargs.pop("name", "MyStruct")
    kwargs.update(dict((k, None) for k in args))
    return type(name, (object,), kwargs)

Используется так:

>>> MyStruct = Struct("forename", "lastname")

Эквивалентно:

class MyStruct(object):
    forename = None
    lastname = None

В то время как это:

>>> TestStruct = Struct("forename", age=18, name="TestStruct")

Эквивалентно:

class TestStruct(object):
    forename = None
    age = 18

Обновление

Кроме того, вы можете отредактировать этот код, чтобы очень легко предотвратить назначение других переменные, чем указанные. Просто измените фабрику Struct (), чтобы назначить __ slots __ .

def Struct(*args, **kwargs):
    name = kwargs.pop("name", "MyStruct")
    kwargs.update(dict((k, None) for k in args))
    kwargs['__slots__'] = kwargs.keys()
    return type(name, (object,), kwargs)
10
ответ дан 3 December 2019 в 01:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: