Python: тот же список на входе, но разные выходы - PullRequest
0 голосов
/ 03 декабря 2018

Я передаю список функции и смотрю на вывод.Когда список жестко закодирован, у меня есть ожидаемый результат.Но когда я строю список из строки и передаю этот список с тем же содержимым функции, у меня нет ожидаемого результата.

Первый вызов:

tech = [ "Django", "Zend", "SQLite", "foo" ]

for tech_item in tech:
    print( test_main( tech_item ) )

Второйcall:

raw_txt = "Django,Zend,SQLite,foo"
tech = raw_txt.split( "," )
# At this point if we print "tech" we have:
# [ "Django", "Zend", "SQLite", "foo" ]

for tech_item in tech:
    print( test_main( tech_item ) )

Итак, ввод / кажется идентичным, но вывод отличается.

Когда я сравниваю содержимое двух списков (переименование второго списка: tech2) У меня есть:

print( tech[0], tech2[0] ) #Django Django
print( tech[0] == tech2[0] ) #True
print( type(tech[0]), type(tech2[0]) ) #<class 'str'> <class 'str'>
print( len(tech[0]), len(tech2[0]) ) #6 6

Что мне не хватает?Есть ли у вас какие-либо подсказки, как найти / разрешить это?

Редактировать:

Вывод, который я получил для первого случая:

frameworks
frameworks
SQL
None

Вывод, который я имеюполучил за 2-й случай:

None
None
None
None

функция test_main

Я даю вам функцию test_main, но, боюсь, она вас запутает.Таким образом, Looking_for каждый раз одинаково.Но «tmp» отличается в обоих случаях.

def test_main( looking_for ):
    global tmp
    tmp = None

    get_recursively( languages_tech, looking_for )

    return tmp

get_recursively function

def get_recursively( data, looking_for, last_key="" ):
    if not isinstance( data, (list, dict) ):
        if data is looking_for: #item
            global tmp
            tmp = last_key
    else:
        if isinstance( data, dict ): #Dictionaries
            for key, value in data.items():
                get_recursively( value, looking_for, key )
        else:
            for item in data: #list
                get_recursively( item, looking_for, last_key )

Languages_tech

languages = { "languages": [
"Ruby", "Python", "JavaScript", "ASP.NET", "Java", "C", "C++", "C#", "Swift", "PHP", "Visual Basic", "Bash" ] }

frameworks = { "frameworks" : [
"Django", "Flask", "React", "React Native", "Vue", "Ember", "Meteor", "AngularJS", "Express" , "Laravel", "Symfony", "Zend", "Ruby on Rails" ] }

databases = { "databases" : [
{ "SQL": ["MariaDB", "MySQL", "SQLite", "PostgreSQL", "Oracle", "MSSQL Server"] },
{ "NoSQL": ["Cassandra", "CouchDB", "MongoDB", "Neo4j", "OrientDB", "Redis", "Elasticsearch"] },
{ "ORM Framework": [ "SQLAlchemy", "Django ORM" ] } ] }

languages_tech = { "languages_tech": [ languages, frameworks, databases ]  }

1 Ответ

0 голосов
/ 03 декабря 2018

Короткий ответ

Следующая строка в вашей функции get_recursively() ошибочна

if data is looking_for:

Используйте это вместо

if data == looking_for:

Длинный ответ

a is b оценивается как true, только если a и b имеют одинаковые id.То есть

(a is b) == (id(a) == id(b))

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

>>> a = "Trebuchet"
>>> b = "Trebuchet"
>>> id(a), id(b)
(4416391792, 4416391792)

Обратите внимание, что оба id имеют значение 4416391792.Это также относится к list с (даже если списки не являются одним и тем же объектом и, следовательно, не имеют одинакового id).

>>> a = ["Trebuchet", "Catapult", "Ballista"]
>>> b = ["Trebuchet", "Catapult", "Ballista"]
>>> id(a), id(b)
(4416392200, 4416861640)

>>> id(a[0]), id(b[0])          
(4416391792, 4416391792)

Обратите внимание, что 4416391792 является точнымтот же номер из предыдущего примера.Это показывает, как строки указывают на один и тот же объект.

Но когда вы вводите функцию str.split() ...

>>> a = "Trebuchet;Catapult;Ballista".split(';')
>>> b = ["Trebuchet", "Catapult", "Ballista"]
>>> id(a[0]), id(b[0])          
(4416392240, 4416391792)

id(b[0]) остается на 4416391792, мыЯ видел это раньше.Но теперь обратите внимание, что str.split() создает новый строковый объект с id = 4416392240 в списке !!!

Это лежит в основе принципа, почему data is looking_for оценивается как ложное.

Конечно, is имеет свои достоинства.Например, мы делаем a is None, а не a == None ( Подробнее ).Но важно различать, когда использовать is и когда использовать ==.При сравнении литералов для таких значений, как строки, списки или кортежи, используйте ==.


Дополнительная информация:

Почему сравнение строкв Python использование '==' или 'is' иногда приводит к другому результату?

Другой пример, где переменные могут иметь конгруэнтные строковые литералы, но разные id s.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...