Свойства атрибута Django queryset [duplicate]

Существуют различные альтернативные подходы, которые мы можем использовать для предложения IN в PreparedStatement.

  1. Использование одиночных запросов - самая медленная производительность и ресурсоемкость
  2. Использование StoredProcedure - самая быстрая, но база данных специфический
  3. Создание динамического запроса для PreparedStatement - Хорошая производительность, но не получает преимущества кэширования, и PreparedStatement перекомпилируется каждый раз.
  4. Использовать NULL в запросах PreparedStatement - Оптимальная производительность, отлично работает, когда вы знаете предел аргументов предложения IN. Если ограничений нет, вы можете выполнять запросы в пакетном режиме. Пример фрагмента кода;
        int i = 1;
        for(; i <=ids.length; i++){
            ps.setInt(i, ids[i-1]);
        }
    
        //set null for remaining ones
        for(; i<=PARAM_SIZE;i++){
            ps.setNull(i, java.sql.Types.INTEGER);
        }
    

Здесь вы можете узнать подробнее об этих альтернативных подходах здесь .

194
задан Matthew Green 10 June 2015 в 19:22
поделиться

10 ответов

Здесь вы можете посмотреть полный пример:

Introspection может использоваться для разных целей, один из которых представлен в «Dive Into Python» - это просто способ динамически добавлять функциональность (плагин) в ваше приложение.

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

Взяв пример «Dive Into Python» - простое приложение для извлечения атрибута из файла другого файла - вы можете добавить обработка нового формата файла без внесения изменений в исходное приложение.

Я рекомендую вам закончить книгу. Когда вы читаете, все станет более ясным.

53
ответ дан John McGehee 15 August 2018 в 19:46
поделиться
  • 1
    Я думаю, что могу понять концепцию самоанализа. Что действительно поражает меня, так это использование getattr (). Пойду ли я это лучше, если я просто буду читать дальше? – Terence Ponce 2 November 2010 в 07:01
  • 2
    Да, конечно, вы прочитали часть, которую я отправляю в качестве ссылки? у вас есть действительно конкретное использование getattr () внутри. diveintopython.org/object_oriented_framework/index.html – Alois Cochard 2 November 2010 в 07:03
  • 3
    Я еще не закончил читать. Спасибо за совет. Я приму это как ответ. – Terence Ponce 2 November 2010 в 07:08
  • 4
    Я думаю, что единственный способ полностью понять это - столкнуться с ситуацией, когда вы должны ее использовать или поддерживать. Так оно работает для меня, но я самообразован. – Alois Cochard 2 November 2010 в 07:10
  • 5
    Здесь также очень хороший ответ: bytes.com/topic/python/answers/832252-setattr-getattr-when-use – Josh Brown 23 November 2013 в 04:45

Довольно часто, когда я создаю файл XML из данных, хранящихся в классе, я часто получал ошибки, если атрибут не существовал или имел тип None. В этом случае моя проблема не зная, что такое имя атрибута, как указано в вашем вопросе, а скорее данные, хранящиеся в этом атрибуте.

class Pet:
    def __init__(self):
        self.hair = None
        self.color = None

Если я использовал hasattr для сделайте это, он вернет True, даже если значение атрибута имеет тип None, и это приведет к ошибке моей команды ElementTree set.

hasattr(temp, 'hair')
>>True

Если значение атрибута имело тип None, getattr также вернет его, что приведет к сбою моей команды ElementTree set.

c = getattr(temp, 'hair')
type(c)
>> NoneType

Теперь я использую следующий метод, чтобы позаботиться об этих случаях:

def getRealAttr(class_obj, class_attr, default = ''):
    temp = getattr(class_obj, class_attr, default)
    if temp is None:
        temp = default
    elif type(temp) != str:
        temp = str(temp)
    return temp

Это когда и как я использую getattr.

3
ответ дан btathalon 15 August 2018 в 19:46
поделиться

Я иногда использую getattr(..) для ленивого инициализации атрибутов вторичной важности непосредственно перед тем, как они используются в коде.

Сравните следующее:

class Graph(object):
    def __init__(self):
        self.n_calls_to_plot = 0

    #...
    #A lot of code here
    #...

    def plot(self):
        self.n_calls_to_plot += 1

К этому:

class Graph(object):
    def plot(self):
        self.n_calls_to_plot = 1 + getattr(self, "n_calls_to_plot", 0)

Преимущество второго способа заключается в том, что n_calls_to_plot появляется только вокруг места в коде, где он используется. Это полезно для читаемости, потому что (1) вы можете сразу увидеть, какое значение оно начинает при чтении, как оно используется, (2) оно не вводит отвлечение в метод __init__(..), который в идеале должен быть о концептуальном состоянии класса, а не некоторый счетчик коммунальных услуг, который используется только одним из методов функции по техническим причинам, таким как оптимизация, и не имеет ничего общего со значением объекта.

3
ответ дан Evgeni Sergeev 15 August 2018 в 19:46
поделиться

Другое использование getattr () при реализации инструкции switch в Python. Он использует оба отражения для получения типа case.

import sys

class SwitchStatement(object):
    """ a class to implement switch statement and a way to show how to use gettattr in Pythion"""

    def case_1(self):
        return "value for case_1"

    def case_2(self):
        return "value for case_2"

    def case_3(self):
        return "value for case_3"

    def case_4(self):
        return "value for case_4"

    def case_value(self, case_type=1):
        """This is the main dispatchmethod, that uses gettattr"""
        case_method = 'case_' + str(case_type)
        # fetch the relevant method name
        # Get the method from 'self'. Default to a lambda.
        method = getattr(self, case_method, lambda: "Invalid case type")
        # Call the method as we return it
        return method()

def main(_):
    switch = SwitchStatement()
    print swtich.case_value(_)

if __name__ == '__main__':
    main(int(sys.argv[1]))
1
ответ дан hoefling 15 August 2018 в 19:46
поделиться

Вот быстрый и грязный пример того, как класс может запускать разные версии метода сохранения, в зависимости от того, какую операционную систему он выполняет при использовании getattr().

import os

class Log(object):
    def __init__(self):
        self.os = os.name
    def __getattr__(self, name):
        """ look for a 'save' attribute, or just 
          return whatever attribute was specified """
        if name == 'save':
            try:
                # try to dynamically return a save 
                # method appropriate for the user's system
                return getattr(self, self.os)
            except:
                # bail and try to return 
                # a default save method
                return getattr(self, '_save')
        else:
            return getattr(self, name)

    # each of these methods could have save logic specific to 
    # the system on which the script is executed
    def posix(self): print 'saving on a posix machine'
    def nt(self): print 'saving on an nt machine'
    def os2(self): print 'saving on an os2 machine'
    def ce(self): print 'saving on a ce machine'
    def java(self): print 'saving on a java machine'
    def riscos(self): print 'saving on a riscos machine'
    def _save(self): print 'saving on an unknown operating system'

    def which_os(self): print os.name

Теперь давайте использовать этот класс в примере:

logger = Log()

# Now you can do one of two things:
save_func = logger.save
# and execute it, or pass it along 
# somewhere else as 1st class:
save_func()

# or you can just call it directly:
logger.save()

# other attributes will hit the else 
# statement and still work as expected
logger.which_os()
12
ответ дан Josh Purvis 15 August 2018 в 19:46
поделиться
# getattr

class hithere():

    def french(self):
        print 'bonjour'

    def english(self):
        print 'hello'

    def german(self):
        print 'hallo'

    def czech(self):
        print 'ahoj'

    def noidea(self):
        print 'unknown language'


def dispatch(language):
    try:
        getattr(hithere(),language)()
    except:
        getattr(hithere(),'noidea')()
        # note, do better error handling than this

dispatch('french')
dispatch('english')
dispatch('german')
dispatch('czech')
dispatch('spanish')
2
ответ дан Kduyehj 15 August 2018 в 19:46
поделиться
  • 1
    Не могли бы вы подробнее рассказать о своем решении, добавив немного подробного описания вашего решения? – abarisone 26 March 2015 в 14:30
  • 2
    да добавить другое объяснение другое удалить свой ответ – Para M 12 March 2018 в 10:40

Для меня getattr проще всего объяснить следующим образом:

Позволяет вам вызывать методы на основе содержимого строки вместо ввода имени метода.

Например , вы не можете этого сделать:

obj = MyObject()
for x in ['foo', 'bar']:
    obj.x()

, поскольку x не относится к типу «builtin», а «str». Однако вы можете это сделать:

obj = MyObject()
for x in ['foo', 'bar']:
    getattr(obj, x)()

Он позволяет динамически подключаться к объектам на основе вашего ввода. Я нашел это полезным при работе с пользовательскими объектами и модулями.

72
ответ дан NuclearPeon 15 August 2018 в 19:46
поделиться

Довольно распространенный вариант использования для getattr - отображение данных в функции.

Например, в веб-среде, такой как Django или Pylons, getattr упрощает сопоставление URL веб-запроса с функцией, которая будет обрабатывать ее. Если вы посмотрите, например, на капот маршрутизации Pylons, вы увидите, что (по крайней мере, по умолчанию) он разбивает URL-адрес запроса, например:

http://www.example.com/customers/list

на «клиентов» и «клиентов», список". Затем он ищет класс контроллера с именем CustomerController. Предполагая, что он находит класс, он создает экземпляр класса, а затем использует getattr для получения своего метода list. Затем он вызывает этот метод, передавая ему запрос в качестве аргумента.

Как только вы поймете эту идею, становится очень просто расширить функциональность веб-приложения: просто добавьте новые методы в классы контроллера и затем создайте ссылки на своих страницах, которые используют соответствующие URL-адреса для этих методов. Все это стало возможным благодаря getattr.

40
ответ дан Robert Rossney 15 August 2018 в 19:46
поделиться
  • 1
    +1 для указания "отображения данных в функции" – Philip007 13 October 2012 в 19:53

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

Сценарий

Предположим, что ваша структура каталогов выглядит следующим образом:

- superheroes.py
- properties.py

И , у вас есть функции для получения информации о Thor, Iron Man, Doctor Strange в superheroes.py. Вы очень хорошо записываете свойства всех из них в properties.py в компактном dict, а затем получаете к ним доступ.

properties.py

thor = {
    'about': 'Asgardian god of thunder',
    'weapon': 'Mjolnir',
    'powers': ['invulnerability', 'keen senses', 'vortex breath'], # and many more
}
iron_man = {
    'about': 'A wealthy American business magnate, playboy, and ingenious scientist',
    'weapon': 'Armor',
    'powers': ['intellect', 'armor suit', 'interface with wireless connections', 'money'],
}
doctor_strange = {
    'about': ' primary protector of Earth against magical and mystical threats',
    'weapon': 'Magic',
    'powers': ['magic', 'intellect', 'martial arts'],
}

Теперь, скажем, вы хотите вернуть возможности каждого из них по запросу в superheroes.py. Таким образом, есть функции, такие как

from .properties import thor, iron_man, doctor_strange


def get_thor_weapon():
    return thor['weapon']


def get_iron_man_bio():
    return iron_man['about']


def get_thor_powers():
    return thor['powers']

... и другие функции, возвращающие разные значения на основе ключей и супергероя.

С помощью getattr вы можете сделать что-то вроде:

from . import properties


def get_superhero_weapon(hero):
    superhero = getattr(properties, hero)
    return superhero['weapon']


def get_superhero_powers(hero):
    superhero = getattr(properties, hero)
    return superhero['powers']

Вы значительно сократили количество строк кода, функций и повторений!

О, и, конечно, если у вас есть плохие имена, такие как properties_of_thor для переменных , они могут быть сделаны и доступны, просто выполняя

def get_superhero_weapon(hero):
    superhero = 'properties_of_{}'.format(hero)
    all_properties = getattr(properties, superhero)
    return all_properties['weapon']

ПРИМЕЧАНИЕ. Для этой конкретной проблемы могут быть более разумные способы справиться с ситуацией, но идея состоит в том, чтобы дать представление об использовании getattr в правильных местах, чтобы писать более чистый код.

4
ответ дан unixia 15 August 2018 в 19:46
поделиться

Объекты в Python могут иметь атрибуты (фактически, каждый объект имеет встроенные атрибуты - атрибуты данных и методы (функции - это значения, т. е. объекты), чтобы работать с ними). ​​

Например у вас есть объект person, который имеет несколько атрибутов: name, gender и т. д.

Доступ к этим атрибутам (будь то методы или объекты данных) обычно записывается: person.name, person.gender, person.the_method() и т. д.

Но что, если вы не знаете имя атрибута в момент написания программы? Например, у вас есть имя атрибута, хранящееся в переменной под названием attr_name.

, если

attr_name = 'gender'

, вместо записи

gender = person.gender

вы можете write

gender = getattr(person, attr_name)

Некоторая практика:

Python 3.4.0 (default, Apr 11 2014, 13:05:11)

>>> class Person():
...     name = 'Victor'
...     def say(self, what):
...         print(self.name, what)
... 
>>> getattr(Person, 'name')
'Victor'
>>> attr_name = 'name'
>>> person = Person()
>>> getattr(person, attr_name)
'Victor'
>>> getattr(person, 'say')('Hello')
Victor Hello

getattr поднимет AttributeError, если атрибут с заданным именем не существует в object:

>>> getattr(person, 'age')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'age'

Но вы можете передать значение по умолчанию в качестве третьего аргумента, которое будет возвращено, если такой атрибут не существует:

>>> getattr(person, 'age', 0)
0

Вы можете использовать getattr вместе с dir для повторения всех имен атрибутов и получения их значений:

>>> dir(1000)
['__abs__', '__add__', ..., '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']

>>> obj = 1000
>>> for attr_name in dir(obj):
...     attr_value = getattr(obj, attr_name)
...     print(attr_name, attr_value, callable(attr_value))
... 
__abs__ <method-wrapper '__abs__' of int object at 0x7f4e927c2f90> True
...
bit_length <built-in method bit_length of int object at 0x7f4e927c2f90> True
...

>>> getattr(1000, 'bit_length')()
10

Практическое использование для этого было бы найти все методы, имена которых начинаются с test и вызывают их .

Как и в getattr , имеется setattr , что позволяет вам установить атрибут объекта, имеющего его имя:

>>> setattr(person, 'name', 'Andrew')
>>> person.name  # accessing instance attribute
'Andrew'
>>> Person.name  # accessing class attribute
'Victor'
>>>
224
ответ дан warvariuc 15 August 2018 в 19:46
поделиться
  • 1
    Поэтому мне кажется, что getattr(..) следует использовать в двух сценариях: 1. когда имя атрибута является значением внутри переменной (например, getattr(person, some_attr)) и 2. когда нам нужно использовать третий позиционный аргумент для значения по умолчанию значение (например, getattr(person, 'age', 24)). Если я вижу сценарий, подобный getattr(person, 'age'), мне кажется, что он идентичен person.age, что заставляет меня думать, что person.age более Pythonic. Это верно? – wpcarro 24 October 2016 в 22:01
  • 2
    @wpcarro да, правильно – warvariuc 14 August 2018 в 06:09
Другие вопросы по тегам:

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