Python __ init __ setattr на аргументах?

Для переменной класса или переменной экземпляра

  1. щелкают правой кнопкой по переменной в представлении схемы
  2. , выбор "Переключает Контрольную точку"
  3. Затем в представлении breapkoints, можно щелкнуть правой кнопкой по получающейся записи
  4. избранные "свойства точек прерывания"
  5. отмена выбора "Доступ к полю".
5
задан lesmana 13 August 2012 в 16:23
поделиться

8 ответов

Держите. Да, это уродливый злой взлом. Да, объекту нужна переменная __dict__. Но эй, это аккуратный маленький лайнер!

def __init__(self):
    self.__dict__.update(locals())

Конструктор может принимать аргументы любого типа.

class test(object):
    def __init__(self, a, b, foo, bar=5)...

a = test(1,2,3)
dir(a)

['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a', 'b', 'foo', 'bar', 'self']

Он также будет включать self, но вы можете легко удалить это или создать свою собственную функцию обновления, которая игнорирует self.

7
ответ дан 18 December 2019 в 06:23
поделиться

Вы можете использовать inspect.getargspec и инкапсулировать его как декоратор. Поиск необязательных аргументов и аргументов ключевого слова немного сложен, но это должно сработать:

def inits_args(func):
    """Initializes object attributes by the initializer signature"""
    argspec = inspect.getargspec(func)
    argnames = argspec.args[1:]
    defaults = dict(zip(argnames[-len(argspec.defaults):], argspec.defaults))
    @functools.wraps(func)
    def __init__(self, *args, **kwargs):
        args_it = iter(args)
        for key in argnames:
            if key in kwargs:
                value = kwargs[key]
            else:
                try:
                    value = args_it.next()
                except StopIteration:
                    value = defaults[key]
            setattr(self, key, value)
        func(self, *args, **kwargs)
    return __init__

Вы можете использовать его так:

class Foo(object):
    @inits_args
    def __init__(self, spam, eggs=4, ham=5):
        print "Foo(%r, %r, %r)" % (self.spam, self.eggs, self.ham)
6
ответ дан 18 December 2019 в 06:23
поделиться

Нет хорошего способа получить аргументы в виде списка, если они указаны индивидуально в сигнатуре функции. Вы, вероятно, сможете что-то сделать с помощью inspect или frame hacks, но это будет уродливее, чем просто изложить это, как вы это сделали.

4
ответ дан 18 December 2019 в 06:23
поделиться

Вы можете сделать это, используя самоанализ аргументов, но код будет длиннее, чем код, который вы пытаетесь заменить. Особенно если вы работаете с кВт, что, возможно, придется сделать.

Этот короткий код работает в большинстве случаев (улучшен по сравнению с примером неизвестных):

>>> class Foo:
...   def __init__(self, labamba, **kw):
...       params = locals().copy()
...       del params['self']
...       if 'kw' in params:
...           params.update(params['kw'])
...           del params['kw']
...       self.__dict__.update(params)

Но это уродливый хакер, который делает код менее читабельным без какой-либо особой причины, кроме лени , так что не делай этого. А также, как часто у вас на самом деле есть классы, которые имеют более 5-6 параметров инициализации?

2
ответ дан 18 December 2019 в 06:23
поделиться

Функционально LINQ - это не что иное, как синтаксическое упрощение выражения монад. Linq to Objects (понимание списков - даже это уже было бы чрезвычайно полезно), о котором вы говорили, является лишь одним из возможных приложений этого (аналогичного List-Monad в Haskell).

Если вы пишете

from x in expr1
from y in expr2
select x + y

, это не что иное, как

do
    x <- expr1
    y <- expr2
    return $ x + y

в Haskell.

Конкретные действия зависят от определенных пользователем Linq-провайдеров (методов расширения), из которых Linq .Enumerable - это всего лишь одна реализация, включающая IEnumerable s.

Предоставляя один, вы можете создать совершенно новую LINQ-семантику для своих типов.

Пример:

2
ответ дан 18 December 2019 в 06:23
поделиться

Как насчет насчет наследования от специального класса? Я думаю, что это более явный и гибкий способ:

class InitMe:
    def __init__(self, data):
        if 'self' in data:
             data = data.copy()
             del data['self']
        self.__dict__.update(data)


class MyClassA(InitMe):
    def __init__(self, ivar1, ivar2, ivar3 = 'default value'):
        super().__init__(locals())


class MyClassB(InitMe):
    def __init__(self, foo):
        super().__init__({'xxx': foo, 'yyy': foo, 'zzz': None})
# or    super().__init__(dict(xxx=foo, yyy=foo, zzz=None))

class MyClassC(InitMe):
    def __init__(self, foo, **keywords):
        super().__init__(keywords)
0
ответ дан 18 December 2019 в 06:23
поделиться

Попробуйте inspect.getargspec :

In [31]: inspect.getargspec(C.__init__)

Out[31]: ArgSpec(args=['self', 'ivar1', 'ivar2', 'ivar3', 'optional'],

                 varargs=None, keywords=None, defaults=(False,))
3
ответ дан 18 December 2019 в 06:23
поделиться

Мне больше всего нравится эта форма, не слишком длинная, с возможностью копирования и вставки, и с возможностью подкласса:

class DynamicInitClass(object):
      __init_defargs=('x',)
      def __init__(self,*args,**attrs):
        for idx,val in enumerate(args): attrs[self.__init_defargs[idx]]=val
        for key,val in attrs.iteritems(): setattr(self,key,val)
1
ответ дан 18 December 2019 в 06:23
поделиться
Другие вопросы по тегам:

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