Уведомления

Группа в Telegram: @pythonsu

#1 Апрель 13, 2019 16:06:32

vanvanov
Зарегистрирован: 2013-03-31
Сообщения: 252
Репутация: +  4  -
Профиль   Отправить e-mail  

Изменение элементов списка

Приветствую!
Заранее извиняюсь, если слишком нубский вопрос или непонятно, чего хочу.
Допустим, есть такой код:

 #!/usr/bin/python3
# -*- coding: UTF-8 -*-
class Block:
    
    def __init__(self):
        self._text = ''
        self._type = ''
class Blocks:
    
    def __init__(self):
        self._blocks = []
    
    def add(self):
        self._blocks.append(Block())
    
    def transc(self):
        for block in self._blocks:
            if block._type == 'comment':
                block._type = 'transc'
Конкретно вопрос про присваивание внутри Blocks.transc. У меня достаточно давно возникла ситуация, когда изменение элементов списка внутри класса почему-то не срабатывало (не приводило к изменению self._blocks). Отследить проблему тогда не удалось, но с этого времени побаиваюсь делать просто что-то типа
 block._type =
и делаю
 self._blocks[i]._type =
. Вторая конструкция срабатывает всегда, но она слишком громоздкая. Поэтому вопрос: всегда ли будет работать присваивание по типу
 block._type =
и есть ли тут какие-нибудь подводные камни?

Отредактировано vanvanov (Апрель 13, 2019 19:49:01)

Офлайн

#2 Апрель 14, 2019 01:30:13

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10022
Репутация: +  857  -
Профиль   Отправить e-mail  

Изменение элементов списка

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

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

Так что в идеале Block() должен иметь методы для установки полей. А Blocks.add() должен иметь аргумент принятия блока (Block() должен создаваться и подаваться снаружи, а не создаваться внутри).



Офлайн

#3 Апрель 14, 2019 10:13:22

vanvanov
Зарегистрирован: 2013-03-31
Сообщения: 252
Репутация: +  4  -
Профиль   Отправить e-mail  

Изменение элементов списка

Если поля не могут меняться снаружи, то метод transc() вообще ничего никогда не сделает, так как все блоки всегда будут пустыми.
Ничего не понял. Можете привести пример? У меня блоки не пустые:
 #!/usr/bin/python3
# -*- coding: UTF-8 -*-
class Block:
    
    def __init__(self):
        self._text = ''
        self._type = ''
class Blocks:
    
    def __init__(self):
        self._blocks = []
    
    def add(self):
        for i in range(5):
            self._blocks.append(Block())
    
    def change(self):
        for i in range(len(self._blocks)):
            self._blocks[i]._type = str(i)
        self._blocks[3]._type = 'comment'
    
    def transc(self):
        for block in self._blocks:
            if block._type == 'comment':
                block._type = 'transc'
    
    def print(self):
        for i in range(len(self._blocks)):
            print(i,':',self._blocks[i]._type)
    
    def run(self):
        self.add()
        self.change()
        self.transc()
        self.print()
if __name__ == '__main__':
    Blocks().run()
Так что в идеале Block() должен иметь методы для установки полей
У меня класс Block только хранит параметры, не более. Пользуюсь вместо словаря, потому что словарь в коде выглядит слишком громоздко и не всегда удобен. А здесь я просто вызвал класс, и он создал все нужные мне переменные - я могу не опасаться получить KeyError.

Офлайн

#4 Апрель 14, 2019 13:33:06

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Изменение элементов списка

vanvanov
когда изменение элементов списка внутри класса почему-то не срабатывало
надо разбираться а не опасаться.
Подводных камней в использовании списков внутри классов нет.
vanvanov
Пользуюсь вместо словаря
Тогда не надо подчеркивания ставить первой буквой. Так принято делать для закрытых для доступа полей
vanvanov
я могу не опасаться получить KeyError.
Для этого есть метод get
 >>> a={}
>>> a.get(1,2)
2
.



Офлайн

#5 Апрель 14, 2019 14:29:40

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10022
Репутация: +  857  -
Профиль   Отправить e-mail  

Изменение элементов списка

vanvanov
Ничего не понял. Можете привести пример? У меня блоки не пустые:
Так ты первый код в вопросе вообще другой написал. В самом начале вопроса код вообще бессмысленный.

vanvanov
У меня класс Block только хранит параметры, не более.
Значит они не должны быть приватными, как написал doza_and.

vanvanov
Поэтому вопрос: всегда ли будет работать присваивание по типу
  
block._type =
и есть ли тут какие-нибудь подводные камни?
Будет работать, никаких подводных камней тут нет. Поизучай тему привязывания имён в питоне.
https://docs.python.org/3/reference/executionmodel.html#naming-and-binding



Офлайн

#6 Апрель 14, 2019 20:59:26

vanvanov
Зарегистрирован: 2013-03-31
Сообщения: 252
Репутация: +  4  -
Профиль   Отправить e-mail  

Изменение элементов списка

doza_and
Тогда не надо подчеркивания ставить первой буквой. Так принято делать для закрытых для доступа полей
Я в курсе, но как еще различать переменные и методы? Венгерская нотация в Питоне как-то не прижилась. Имхо, отмечать переменные как “закрытые для доступа” достаточно логично, поскольку код яснее, когда какой-либо метод класса возвращает значение, а не когда сторонний класс дергает не свои переменные. К тому же, есть ведь и __такие, и __такие__ закрытые методы. Но это все сугубо мое имхо. Объясните, пожалуйста, как лучше.

Офлайн

#7 Апрель 15, 2019 01:10:30

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10022
Репутация: +  857  -
Профиль   Отправить e-mail  

Изменение элементов списка

vanvanov
Я в курсе, но как еще различать переменные и методы?
Прочитай PEP8
https://www.python.org/dev/peps/pep-0008/#naming-conventions
https://www.python.org/dev/peps/pep-0008/#designing-for-inheritance
Public attributes should have no leading underscores.



For simple public data attributes, it is best to expose just the attribute name, without complicated accessor/mutator methods. Keep in mind that Python provides an easy path to future enhancement, should you find that a simple data attribute needs to grow functional behavior. In that case, use properties to hide functional implementation behind simple data attribute access syntax.

vanvanov
Объясните, пожалуйста, как лучше.
Ты бы читал книги, там бы тебя отослали к PEP'ам. А так ты пытаешься сам догадаться, что и зачем. Потеряешь время только впустую и придёшь всё равно к тому, что в книгах и документации описано.



Отредактировано py.user.next (Апрель 18, 2019 05:22:23)

Офлайн

#8 Апрель 18, 2019 02:37:44

vanvanov
Зарегистрирован: 2013-03-31
Сообщения: 252
Репутация: +  4  -
Профиль   Отправить e-mail  

Изменение элементов списка

Спасибо за рекомендации.
Только что натолкнулся на пример:

 #!/usr/bin/python3
# -*- coding: UTF-8 -*-
import urllib.parse
class Test:
    
    def __init__(self,url):
        self._url = url
    
    '''
    def quote(self):
        self._url = list(self._url)
        for symbol in self._url:
            if not symbol in (':','/','=','&','?'):
                symbol = urllib.parse.quote(symbol)
        self._url = ''.join(self._url)
    '''
    
    def quote(self):
        self._url = list(self._url)
        for i in range(len(self._url)):
            if not self._url[i] in (':','/','=','&','?'):
                self._url[i] = urllib.parse.quote(self._url[i])
        self._url = ''.join(self._url)
    
    def report(self):
        print('"' + self._url + '"')
    
    def run(self):
        self.quote()
        self.report()
if __name__ == '__main__':
    Test('https://www.multitran.com/m.exe?l1=2&l2=1&s=компьютер').run()
Почему процедура quote работает, а закомментированная процедура - не работает?

Офлайн

#9 Апрель 18, 2019 05:30:59

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10022
Репутация: +  857  -
Профиль   Отправить e-mail  

Изменение элементов списка

vanvanov
Почему процедура quote работает, а закомментированная процедура - не работает?
Потому что имя symbol сначала привязано к одному объекту, а потом в цикле оно просто перепривязывается к другому объекту. С первым объектом ничего не происходит, от него отвязывается единственное имя и он просто остаётся в списке, каким и был до привязывания имени к нему.

Вот пример
  
>>> n = 1
>>> n
1
>>> n = 2
>>> n
2
>>>
Имя n привязали к объекту число со значением 1. Затем имя n привязали к другому объекту число со значением 2. Как только имя n привязали к другому объекту, первый объект, потеряв своё имя, высвободился из памяти (уничтожился).

К одному и тому же объекту может быть привязано много имён
  
>>> a = b = c = 1
>>> a
1
>>> b
1
>>> c
1
>>>
Как только объект теряет все свои имена, он удаляется из памяти. Там не только имена влияют на это, есть ещё и безымянные ссылки. Если объект находится в списке, который имеет имя и висит в памяти, то объект не будет удалён, потому что список на него ссылается (имеет невидимую ссылку). Но как только список потеряет имя и он при этом нигде не будет содержаться сам (в списке или кортеже), все объекты в этом списке удалятся и сам список тоже.

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



Отредактировано py.user.next (Апрель 18, 2019 05:45:58)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version