Подтвердить что ты не робот

Зачем использовать __setattr__ в python?

Я не знаю, зачем использовать __setattr__ вместо простой ссылки, например x.a=1.

Я понимаю этот пример:

class Rectangle:
    def __init__(self):
        self.width = 0
        self.height = 0


x=Rectangle()
x.width=20
x.__setattr__('height',30)
setattr(x,'width',99)

но не получается использовать код в зависимости от строки ('height').

Не могли бы вы объяснить мне, что есть преимущества __setattr__?

4b9b3361

Ответ 1

Вы не называете это самим. Период. Если вам нужно использовать строку, потому что вы заранее не знаете ее имя (очень плохая идея в 99% случаев, когда, возможно, это и нужно, почти всегда дикт или список - лучший/более здравый выбор), вы используете встроенная функция setattr.

Однако он вам нужен - когда вы делаете a.x = ..., который выполняется как a.__setattr__('x', ...) (это упрощает упрощение). И некоторые объекты перегружают его, чтобы позволить некоторые обманывать, например. для подражания неизменности. См. документацию по "специальным методам" .

Ответ 2

__setattr__ - метод класса, который вызывается setattr встроенным методом. То есть, если __setattr__ задан в данном классе. Чаще всего вы не объявляете свою собственную версию __setattr__, поэтому я предполагаю, что вы спрашиваете, что такое метод setattr.

Предположим, что у вас есть var с именем атрибута, который вы хотите установить, а не просто зная имя:

class A(object):
    def doSth(self, name, val):
        setattr(self, name, val)

невозможно сделать с self.name = val

Кроме того, общее использование имеет ключевое слово args:

class A(object):
    def __init__(self, *args, **kwargs):
        for k,v in kwargs.items():
            setattr(self, k, v)

Ответ 3

Я могу представить себе приложение, в котором, например, вы переопределяете __setattr__ и __getattr__, чтобы предоставить объектный доступ к какой-либо другой структуре данных, которая не хранится в памяти. Например, вы можете создать объект, в котором foo.CustomerName = "John" обновлен столбец CustomerName в строке базы данных, на который указывает foo, чтобы содержать значение "John". I.e., foo.__setattr__ будет использовать имя и значение атрибута для создания команды для обновления базы данных на диске. Мне не хотелось бы писать такую ​​вещь, но это было бы возможно.

Ответ 4

Обратите внимание, что __xxx__ являются методами перегрузки операторов класса и как таковые должны использоваться только в особых ситуациях, а не в случаях, как в вашем примере.

Например, __setattr__ перехватывает все назначения атрибутов и может использоваться для изменения поведения вашего класса, когда значение присваивается атрибуту.

Ответ 5

__setattr__ может использоваться для отражения, где при запуске может создаваться призрак на объекте Rectangle, на нем больше http://en.wikipedia.org/wiki/Reflection_%28computer_science%29

class Rectangle:
    def __init__(self):
        #... code ...

x = Rectangle()
#x.__setattr__('newProperty',30)      Edited after comment
setattr(x, 'newProperty', 30)
print x.newProperty #>>> 30

Ответ 6

class Name(object):
    pass

obj=Name()

#just i have created object two way 
#first

obj.a="first"
print obj.a

#answer= "first"
#second

obj.__setattr__('b','second')
print obj.a
#answer= "second"

Ответ 7

Первое использование __setattr__ должно быть перезаписано в определении класса.

class Foo ( object ) :

    def __init__ ( self ) :
        self.x = 'looser'

    def __setattr__ ( self, name, value ) :
        if name == 'x' :
            print( 'Hello, {} !'.format( value ) )
            self.x = value

Проблема, Foo() будет печатать бесконечную последовательность:

'Hello, looser !'

Второе использование - это то, что, когда вы это делаете, вы можете вызвать setattr из родительского класса (object по умолчанию), чтобы избежать бесконечной рекурсии:

class Foo ( object ) :

    def __setattr__ ( self, name, value ) :
        self.bar( name, value )
        object.__setattr__( self, name, value )

    def bar ( self, name, value ) :
        print( 'Setting {} to {}.'.format( name, value ) )

И поэтому:

f = Foo()

>> 'Hello, winner !'

f.x

>> 'winner'