Python импортирует атрибуты класса в локальное пространство имен методов

Некоторое время я задавался вопросом, есть ли более простой способ назначить атрибуты класса методу локального пространства имен. Например, в методе dosomething я явно ссылаюсь на self.a и self.b:

class test:
    def __init__(self):
        self.a = 10
        self.b = 20

    def dosomething(self):
        a = self.a
        b = self.b
        return(a + b)

Но иногда у меня много переменных (более 10), и он становится беспорядочным, чтобы набирать и смотреть - у меня бы получилось множество операторов var = self.var в начале метода.

Есть ли способ сделать это более компактным способом? (Я знаю, что обновление local() не является хорошей идеей)

Изменить: В идеале я хочу:

def dosomething(self):
    populate_local_namespace('a', 'b')
    return(a + b)

Ответ 1

Q. Есть ли способ сделать это более компактным способом?

1. Если переменные доступны только для чтения, было бы разумно Pythonic отказаться от метода доступа с несколькими переменными:

class Test:

    def __init__(self):
        self.a = 10
        self.b = 20
        self.c = 30

    def _read_vars(self):
        return self.a, self.b, self.c

    def dosomething(self):
        a, b, c = self._read_vars()
        return a + b * c

    def dosomethingelse(self):
        a, b, c = self._read_vars()
        return a - b * c

Если переменные не доступны только для чтения, лучше придерживаться self.inst_var = value. Это нормальный способ написания кода Python, и обычно это то, что ожидают большинство людей.


2. Время от времени вы увидите, как люди сокращают self с более коротким именем переменной. Он используется, когда преимущества удобочитаемости превышают читаемость при использовании имени нестандартной переменной:

def updatesomethings(s):
    s.a, s.b, s.c = s.a + s.c, s.b - s.a, s.c * s.b

3. Другой способ обработки переменной экземпляра очень большого числа - хранить их в изменяемом контейнере для удобства упаковки и распаковки:

class Test:

    def __init__(self, a, b, c, d, e, f, g, h, i):
        self._vars = [a, b, c, d, e, f, g, h, i]

    def fancy_stuff(self):
        a, b, c, d, e, f, g, h, i = self._vars
        a += d * h - g
        b -= e * f - c
        g = a + b - i
        self._vars[:] = a, b, c, d, e, f, g, h, i

4. Существует также подход к манипулированию словарями, который будет работать, но у него есть запах кода, который большинство Pythonistas избежал бы:

def updatesomethings(self):
    a = 100
    b = 200
    c = 300
    vars(self).update(locals())
    del self.self

Ответ 2

Вы можете легко решить эту проблему с помощью компромисса, сохранив переменные в словаре.

data = {}
copy_to_local_variables = ["a", "b", "c", "d"]
for var_name in copy_to_local_variables:
    data[var_name] = getattr(self, var_name)

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

Ответ 3

Я нашел другой способ:

def dosomething(self):
    for key in ['a', 'b']:
       exec('{} = self.{}'.format(key, key))

    return(a + b)

Я не знаю, опасно это или нет. Было бы здорово, если бы кто-то мог прокомментировать это.