Создание пустого списка внутри функции и передача его в глобальную область видимости.(инициализация пустого списка в функции) - PullRequest
0 голосов
/ 15 февраля 2019

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

def addlst(l, item):
        """add an item to a list"""
        l = list()#this line essentially does nothing. 
        if type(item) == str:    
            l.append(item.capitalize())
            return l
            print(l)
        else:
            l.append(item)
            return l
            print(l)

если я передаю что-то вроде:

addlst(people, 'kev')

Я получаю ошибку:

NameError: name 'people' is not defined

но, очевидно, если я определяю людей как пустой списокэто работает отлично.

Возможно ли то, что я делаю?Я знаю, что в нынешнем виде строка

l = list()

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

Ответы [ 3 ]

0 голосов
/ 15 февраля 2019

Когда вы пишете addlst(people, 'kev'), вы сообщаете своему коду, что вы хотите выполнить функцию addlst с переменной с именем people в качестве первого параметра.

Проблема в : вы никогда не устанавливаете эту переменную!

Есть много способов для этого;Вы можете либо инициализировать пустой список перед вызовом функции:

people = []
addlst(people, 'kev')

Или сделать параметр необязательным со значением по умолчанию:

 def addlst(item, l = None):
   """add an item to a list"""
    if l is None:
        l = []
    if type(item) == str:    
        l.append(item.capitalize())
        return l
    else:
        l.append(item)
        return l

Но это может быть сложно, так как списки изменяемые объекты .

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

Aпоследний способ

В конце концов, вы также можете сократить свой код, выполнив что-то вроде этого:

mylist = []
item = "test"
mylist.append(item.capitalize() if type(item) == str else item)
0 голосов
/ 15 февраля 2019

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

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

  2. Если функция принимает аргумент, есть две опции.Во-первых, вы можете изменить его, и ваша функция вернет None, или вы можете создать новое значение на основе аргумента и вернуть его, оставив аргумент без изменений.Очень редко, если вообще когда-либо, если ваша функция изменяет аргумент и возвращает значение.

  3. Если ваша функция возвращает новый список, вы можете необязательно взять список для изменения или создать новый список внутри вашей функции.

Не имеет отношения к делу, но вам все равно, какой тип item, толькочто это то, что имеет capitalize метод, который вы можете вызвать.Просто попробуйте;если этого не произойдет, то получится AttributeError, который вы можете поймать, и в этом случае вы можете просто использовать item как есть.


Собирая все это вместе, я рекомендую третий подход,add_to_list примет элемент в качестве первого аргумента и необязательный список в качестве второго аргумента.Если список не указан, функция создаст новый список.В любом случае вы добавите в список соответственно измененный элемент и вернете его.

def add_to_list(item, l=None):
    # Note: this doesn't change the item you pass; it just rebinds
    # the local name item to a *new* string if it succeeds.
    try:
        item = item.capitalize()
    except AttributeError:
        pass

    if l is None:
        l = []

    return l + [item]

Затем вы можете использовать

people = add_to_list('kev')  # people == ['Kev']
people = add_to_list('bob')  # people == ['Bob'], Kev is gone!
people = add_to_list('kev', people)  # people == ['Bob', 'Kev'], Kev is back.

Более эффективная версия, упомянутая ввторой подход изменяет l на месте;в этом случае, однако, у вас есть , чтобы предоставить список;Вы не можете создать новый список.

def add_to_list(item, l):
    try:
        item = item.capitalize()
    except AttributeError:
        pass

    l.append(item)

people = []  # Create the list in the *calling* scope, not in add_to_list
add_to_list('kev')  # TypeError, missing an argument
add_to_list('kev', people)  # people == ['Kev']
add_to_list('bob', people)  # people == ['Kev', 'Bob']

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

def add_to_people(item):
    global people

    try:
        item = item.capitalize()
    except AttributeError:
        pass

    people.append(item)

Теперь add_to_list может работать с глобальным списком people, но без другого списка.

people = []
add_to_people('kev')
add_to_people('bob')

И, наконец, в интересах полного раскрытия, да, add_to_people может создать список, если его еще нет:

def add_to_people(item):
    global people

    try:
        people  # Simply try to evaluate the name
    except NameError:
        people = []

    # ...

Однако, если используетсяглобальное имя, во-первых, плохое, авививифицировать его так, как будто это хуже.По возможности избегайте такого стиля программирования.

0 голосов
/ 15 февраля 2019

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

def f(el):
    global l
    l.append(el)

Тогда

>>> l = []
>>> f(2)
>>> l
[2]
>>> f(3)
>>> l
[2, 3]

Как указано выше, l должен быть объявлен перед использованием f.


Работа с вашимВот некоторые особенности, которые вы могли бы сделать:

def addlst(item):
    """add an item to a list"""
    global l#
    if isinstance(item, str):     # type(item) == str is not recommanded
        item = item.capitalize()
    l.append(item)

Но на самом деле, обратите внимание, что это «привязывает» вашу функцию к работе исключительно со списком с именем l в глобальной области видимости.И, похоже, это не то, что вам нужно, поскольку кажется, что вы хотите иметь возможность передавать несколько объектов списка в вашу функцию.Лучший подход здесь

def addlst(list_, item):
    """add an item to a list"""
    if isinstance(item, str):
        item = item.capitalize()
    list_.append(item)
    return list_
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...