Что лучший (идиоматический) путь состоит в том, чтобы проверить тип переменной Python? [дубликат]

Несколько рекомендаций по экранированию специальных символов в операторах SQL.

Не используйте MySQL , это расширение устарело, используйте MySQLi или PDO .

MySQLi

Для ручного экранирования специальных символов в строке вы можете использовать функцию mysqli_real_escape_string .

Пример:

$mysqli = new mysqli( 'host', 'user', 'password', 'database' );
$mysqli->set_charset( 'charset');

$string = $mysqli->real_escape_string( $string );
$mysqli->query( "INSERT INTO table (column) VALUES ('$string')" );

Для автоматического экранирования значений с помощью подготовленных операторов , используйте mysqli_prepare и mysqli_stmt_bind_param , где для соответствующего преобразования должны быть указаны типы для соответствующих переменных связывания:

Пример:

$stmt = $mysqli->prepare( "INSERT INTO table ( column1, column2 ) VALUES (?,?)" );

$stmt->bind_param( "is", $integer, $string );

$stmt->execute();

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

Итак, если вы используете подготовленный оператор, вы должны указать типы переменных для функции mysqli_stmt_bind_param.

И использование mysqli_real_escape_string для, как сказано в названии, означает экранирование специальных символов в строке, поэтому оно не сделает целые числа безопасными. Цель этой функции - предотвратить разрыв строк в операторах SQL и повреждение базы данных, которое она может вызвать. mysqli_real_escape_string - полезная функция при правильном использовании, особенно в сочетании с sprintf.

Пример:

$string = "x' OR name LIKE '%John%";
$integer = '5 OR id != 0';

$query = sprintf( "SELECT id, email, pass, name FROM members WHERE email ='%s' AND id = %d", $mysqli->real_escape_string( $string ), $integer );

echo $query;
// SELECT id, email, pass, name FROM members WHERE email ='x\' OR name LIKE \'%John%' AND id = 5

$integer = '99999999999999999999';
$query = sprintf( "SELECT id, email, pass, name FROM members WHERE email ='%s' AND id = %d", $mysqli->real_escape_string( $string ), $integer );

echo $query;
// SELECT id, email, pass, name FROM members WHERE email ='x\' OR name LIKE \'%John%' AND id = 2147483647

296
задан Robert 2 July 2015 в 02:00
поделиться

10 ответов

Что происходит, если кто-то передает строку unicode Вашей функции? Или класс, полученный из dict? Или класс, реализовывая подобный dict интерфейс? Следующий код покрывает сначала два случая. При использовании Python 2.6, Вы могли бы хотеть использовать collections.Mapping вместо dict согласно ABC PEP.

def value_list(x):
    if isinstance(x, dict):
        return list(set(x.values()))
    elif isinstance(x, basestring):
        return [x]
    else:
        return None
319
ответ дан Jonathon Reinhart 23 November 2019 в 01:34
поделиться

type(dict()) говорит, "делают новый dict, и затем узнают, каков его тип". Это более быстро для высказывания просто "dict". Но если Вы хотите просто проверить тип, более идиоматический путь isinstance(x, dict).

Примечание, это isinstance также включает подклассы (спасибо Dustin):

class D(dict):
    pass

d = D()
print("type(d) is dict", type(d) is dict)  # -> False
print("isinstance (d, dict)", isinstance(d, dict))  # -> True
57
ответ дан Michael Geary 23 November 2019 в 01:34
поделиться

встроенные типы в Python создали на имена:

>>> s = "hallo"
>>> type(s) is str
True
>>> s = {}
>>> type(s) is dict
True

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

36
ответ дан Albert Visser 23 November 2019 в 01:34
поделиться

Я думаю, что пойду для утки, вводящей подход - "если это будет идти как утка, это шарлатаны как утка, это - утка". Таким образом, Вы должны будете не волноваться о том, если строка будет unicode, или ASCII

Вот то, что я сделаю:

In [53]: s='somestring'

In [54]: u=u'someunicodestring'

In [55]: d={}

In [56]: for each in s,u,d:
    if hasattr(each, 'keys'):
        print list(set(each.values()))
    elif hasattr(each, 'lower'):
        print [each]
    else:
        print "error"
   ....:         
   ....:         
['somestring']
[u'someunicodestring']
[]

эксперты здесь могут прокомментировать этот тип использования ducktyping, я использовал его, но был представлен точному понятию позади него в последнее время и очень взволнован по поводу этого. Таким образом, я хотел бы знать - ли это излишество, чтобы сделать.

8
ответ дан JV. 23 November 2019 в 01:34
поделиться

isinstance предпочтителен по типу, потому что это также оценивает как Верное при сравнении экземпляра объекта с, он - суперкласс, который в основном означает, что у Вас никогда не будет к особому случаю своего старого кода для использования его с подклассами str или dict.

, Например:

 >>> class a_dict(dict):
 ...     pass
 ... 
 >>> type(a_dict()) == type(dict())
 False
 >>> isinstance(a_dict(), dict)
 True
 >>> 

, Конечно, могли бы быть ситуации, где Вы не захотите это поведение, но те - †“hopefully†“намного менее распространенный, чем ситуации, где Вы действительно хотите его.

20
ответ дан Dirk Stoop 23 November 2019 в 01:34
поделиться

Я думаю, что это могло бы быть предпочтено, чтобы на самом деле сделать

if isinstance(x, str):
    do_something_with_a_string(x)
elif isinstance(x, dict):
    do_somethting_with_a_dict(x)
else:
    raise ValueError

, 2 Альтернативных формы, в зависимости от Вашего кода один или другой, вероятно, считают лучше, чем это даже. Не нужно посмотреть перед прыганием

try:
  one, two = tupleOrValue
except TypeError:
  one = tupleOrValue
  two = None

, другой подход от Guido и является формой перегрузки функции, которая оставляет код более открытым законченный.

http://www.artima.com/weblogs/viewpost.jsp?thread=155514

6
ответ дан S.Lott 23 November 2019 в 01:34
поделиться

Это должно работать - так не, нет ничего неправильно с Вашим кодом. Однако это могло также быть сделано с dict:

{type(str()): do_something_with_a_string,
 type(dict()): do_something_with_a_dict}.get(type(x), errorhandler)()

немного более краткий и pythonic разве Вы не сказали бы?

<час>

Редактирование.. Учитывая совет Avisser, код также работает как это и выглядит более хорошим:

{str: do_something_with_a_string,
 dict: do_something_with_a_dict}.get(type(x), errorhandler)()
3
ответ дан nakedfanatic 23 November 2019 в 01:34
поделиться

Я использовал другой подход:

from inspect import getmro
if (type([]) in getmro(obj.__class__)):
    # This is a list, or a subclass of...
elif (type{}) in getmro(obj.__class__)):
    # This one is a dict, or ...

я не могу помнить, почему я использовал это вместо isinstance, хотя...

1
ответ дан Matthew Schinckel 23 November 2019 в 01:34
поделиться

* sigh *

Нет, аргументы проверки типов в python не нужны. Это никогда необходимо.

Если ваш код принимает либо строку, либо объект dict, ваш дизайн нарушается.

Это происходит из-за того факта, что если вы еще не знаете тип объекта в вашей собственной программе вы уже что-то делаете не так.

Проверка типов вредит повторному использованию кода и снижает производительность. Имея функцию, которая выполняет разные вещи в зависимости от типа передаваемого объекта подвержен ошибкам и имеет поведение, более трудное для понимания и поддержки.

У вас есть следующие более разумные опции:

1) Создайте функцию unique_values ​​, которая преобразует дикты в уникальные списки значений:

def unique_values(some_dict):
    return list(set(some_dict.values()))

Сделайте так, чтобы ваша функция предполагала, что передаваемый аргумент всегда является списком. Таким образом, если вам нужно передать строку в функцию, вы просто делаете:

myfunction([some_string])

Если вам нужно передать это диктом, вы делаете:

myfunction(unique_values(some_dict))

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

2) Сделайте две функции, одну, которая принимает списки строк и одну, которая принимает dicts. Вы можете сделать один звонок другого внутри, в наиболее удобном way ( myfunction_dict может создать список строк и вызвать myfunction_list ).

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

0
ответ дан nosklo 23 November 2019 в 01:34
поделиться

You may want to check out typecheck. http://pypi.python.org/pypi/typecheck

Модуль проверки типов для Python

Этот пакет предоставляет мощные средства проверки типов во время выполнения для функций, методов и генераторов Python. Не требуя специального препроцессора или изменений в языке, пакет typecheck позволяет программистам и инженерам по обеспечению качества делать точные утверждения относительно ввода и вывода их кода.

3
ответ дан 23 November 2019 в 01:34
поделиться
Другие вопросы по тегам:

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