Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » Python для новичков
  • » Локально создаваемый объект внутри функции не переопределяется при повторном запуске фукнции [RSS Feed]

#1 Дек. 7, 2022 11:44:47

kambi
Зарегистрирован: 2022-12-07
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Локально создаваемый объект внутри функции не переопределяется при повторном запуске фукнции

Имеем:

 @dataclass
class CounterData:
    counter_id: str
    period_start: datetime
    period_end: datetime
    counter_name: str = ""
    enter_count: int = 0
    exit_count: int = 0
class SensorData:
    def __init__(self, sensor_type: str, sensor_serial: str, counter_data: list[CounterData], sensor_name: str = ""):
        self.sensor_serial = sensor_serial
        self.sensor_name = sensor_name
        self.sensor_type = sensor_type
        self.counters = counter_data
    def __str__(self):
        txt = f'SensorType={self.sensor_type}, SerialNumber={self.sensor_serial}, SensorName={self.sensor_name}'
        if len(self.counters) == 0:
            txt += '\t No counters data.'
        else:
            for counter in self.counters:
                txt += f'\n\tcounter_id={counter.counter_id}, counter_name={counter.counter_name}' \
                       f'\n\t\tperiod= {counter.period_start} - {counter.period_end}' \
                       f'\n\t\tentered= {counter.enter_count} exited= {counter.exit_count}'
        return txt
    def add_counter_data(self, counter_data: CounterData):
        self.counters.append(counter_data)

Далее есть функция:
 def parse_xml(file_name_full: str) -> SensorData | None:
    try:
        xml_tree = ElementTree.parse(file_name_full)
    except ElementTree.ParseError as err:
        print(repr(err))
        return None
    xml_root = xml_tree.getroot()
    namespace = {'ns': 'http://www.tralivali.com/api/v2'}
    s_type = '3Dv2'
    s_serial = xml_root.find('ns:sensor-info/ns:serial-number', namespace).text
    if not s_serial:
        return None
    s_name = file_name_full
    sensor_data = SensorData(sensor_serial=s_serial, sensor_name=s_name, sensor_type=s_type)
    count_lines = xml_root.findall('ns:content/ns:elements/ns:element', namespace)
    for count_line in count_lines:
        line_measurements = count_line.findall('ns:measurements/ns:measurement', namespace)
        for measurement in line_measurements:
            enter_count = int(measurement.find("ns:values/ns:value[@label='fw']", namespace).text)
            exit_count = int(measurement.find("ns:values/ns:value[@label='fw']", namespace).text)
            line_count_data = CounterData(
                counter_id=count_line.find("ns:element-id", namespace).text,
                period_start=datetime.fromisoformat(count_line.find("ns:from", namespace).text),
                period_end=datetime.fromisoformat(count_line.find("ns:to", namespace).text),
                counter_name=count_line.find("ns:element-name", namespace).text,
                enter_count=enter_count,
                exit_count=exit_count
            )
            sensor_data.add_counter_data(line_count_data)
    if len(sensor_data.counters) == 0:
        return None
    else:
        return sensor_data
Данная функция из другой функции в цикле вызывается с разными именами файлов:
 ...
sensor_count_data: Optional[SensorData] = parse_xml(file_name_full)
...

Объясните, пож-та, кто-нибудь почему в объекте sensor_count_data: Optional = parse_xml(file_name_full) поле списка counters (тип CounterData) с каждой итериацией не очищается, а пополняется всен время новыми данными? Внутри функции parse_xml, объект sensor_data же локально создается для передачи данных обратно в место вызова, и по идее каждый вызов этой функции должен же приводить к созданию нового экземпляра, пустого от прежних значений?
Такое ощущение, что объект в строке кода:
 line_count_data = CounterData(.....
создается какой-то статический и он получается общий для всех новых объектов типа SensorData инициализируемых чуть выше этой строки.

Отредактировано kambi (Дек. 7, 2022 11:47:46)

Офлайн

#2 Дек. 7, 2022 12:40:05

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

Локально создаваемый объект внутри функции не переопределяется при повторном запуске фукнции

kambi
  
sensor_data = SensorData(sensor_serial=s_serial, sensor_name=s_name, sensor_type=s_type)
В этой строке где четвёртый аргумент counter_data?



Офлайн

#3 Дек. 7, 2022 12:46:06

kambi
Зарегистрирован: 2022-12-07
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Локально создаваемый объект внутри функции не переопределяется при повторном запуске фукнции

Сорри, это я успел немного определение функции переделать) У меня там было так, со значением по умолчанию:

 def __init__(self, sensor_type: str, sensor_serial: str, counter_data: list[CounterData] = [], sensor_name: str = "")

Офлайн

#4 Дек. 7, 2022 12:47:53

kambi
Зарегистрирован: 2022-12-07
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Локально создаваемый объект внутри функции не переопределяется при повторном запуске фукнции

Думал уже может датаклассы как-то по особому иногда работают). Просто хочу понять причину.

Офлайн

#5 Дек. 7, 2022 13:01:38

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

Локально создаваемый объект внутри функции не переопределяется при повторном запуске фукнции

kambi
Объясните, пож-та, кто-нибудь почему в объекте sensor_count_data: Optional = parse_xml(file_name_full) поле списка counters (тип CounterData) с каждой итериацией не очищается, а пополняется всен время новыми данными?
Потому что там этот список пустой не заменяется на новый список никогда. По мере добавления в него элементов они туда добавляются просто и всё.

kambi
Просто хочу понять причину.
  
>>> def f(n, lst=[]):
...     lst.append(n)
...     return lst
... 
>>> f(1)
[1]
>>> f(2)
[1, 2]
>>> f(3)
[1, 2, 3]
>>> 
>>> f(4, [])
[4]
>>> f(5)
[1, 2, 3, 5]
>>> 
>>> f(6, [])
[6]
>>> f(7, [])
[7]
>>>



Офлайн

#6 Дек. 7, 2022 22:37:23

kambi
Зарегистрирован: 2022-12-07
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Локально создаваемый объект внутри функции не переопределяется при повторном запуске фукнции

py.user.next
Потому что там этот список пустой не заменяется на новый список никогда. По мере добавления в него элементов они туда добавляются просто и всё.
Это правило относится только к значениям по-умолчанию, конкретно к list-ам или как? Где бы про это почитать?
У меня не совсем укладывается пока, пока не прочитаю это правило так и будет “мучать”)) - объект создается внутри функции локально, из функции вышли. Снова вызвали функцию - снова создали объект, включая вложенный объект - почему здесь не создается новый пустой список при присвоении значения по-умолчанию, а в старый, который мы создали на предыдущем вызове и отдали наружу, добавляется?

ПС: исправил определение функции без значения по-умолчанию для counters, передаю при инициализации пустой список - так норм.

Офлайн

#7 Дек. 8, 2022 00:11:35

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

Локально создаваемый объект внутри функции не переопределяется при повторном запуске фукнции

kambi
Это правило относится только к значениям по-умолчанию
Список создаётся там, где определяется функция. Затем ссылка на этот объект присваивается в качестве значения по умолчанию для именованного аргумента функции. Объект продолжает существовать, пока есть хотя бы одна ссылка на него, привязанная к чему-то.

kambi
Где бы про это почитать?
Объекты описаны здесь
https://docs.python.org/3/reference/datamodel.html#objects-values-and-types
Прикрепления объектов к именам описаны здесь
https://docs.python.org/3/reference/executionmodel.html#naming-and-binding

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

kambi
Снова вызвали функцию - снова создали объект
Функция создаётся один раз в месте определения и становится объектом. А вызывается потом много раз один этот объект, который был создан в первый раз.

Вот пример, который иллюстрирует, что функция становится объектом
  
>>> def f(n):
...     f.x += 10
...     return n
... 
>>> f.x = 0
>>> 
>>> f(1)
1
>>> f(2)
2
>>> f(3)
3
>>> 
>>> f.x
30
>>>
Так как функция - это объект, то в ней можно хранить значения. И при каждом вызове это всё та же функция, которая просто несколько раз вызывалась.

Соответственно, раз это объект, то у него есть состояние, которое может меняться. Состояние объекта состоит из набора его свойств (полей) и их значений в каждый конкретный момент. Состояние объекта, привязанного к имени f, включает в себя свойство x и значение этого свойства x. Сначала объект в состоянии x = 0, потом над объектом выполняется операция “вызвать объект-функцию” и объект переходит в состояние x = 10 и остаётся в нём, потом над объектом выполняется операция “вызвать объект-функцию” и объект переходит в состояние x = 20 и остаётся в нём, потом над объектом выполняется операция “вызвать объект-функцию” и объект переходит в состояние x = 30 и остаётся в нём.

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



Отредактировано py.user.next (Дек. 8, 2022 00:33:59)

Офлайн

#8 Дек. 9, 2022 08:41:13

kambi
Зарегистрирован: 2022-12-07
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Локально создаваемый объект внутри функции не переопределяется при повторном запуске фукнции

Всё. Свой по своему случаю я кажется четко понял суть)). Спасибо.

Офлайн

  • Начало
  • » Python для новичков
  • » Локально создаваемый объект внутри функции не переопределяется при повторном запуске фукнции[RSS Feed]

Board footer

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

Powered by DjangoBB

Lo-Fi Version