Как правильно добавить свой метод в namedtuple?

Рейтинг: 2Ответов: 1Опубликовано: 30.03.2023

Есть вот такой "игрушечный" пример

class Car:
    def __init__(self, color, mileage):
        self.color = color
        self.mileage = mileage
    
    def check_mileage(self): 
        if self.mileage > 10000: 
            print('Машина с большим пробегом')
        else: 
            print('Машина с маленьким пробегом')

Но если я пробую переписать это на namedtuple, то с методом проблемы:

from collections import namedtuple

Car = namedtuple('Авто' , 'color mileage check_mileage')

def check_mileage(self): 
        if self.mileage > 10000: 
            print('Машина с большим пробегом')
        else: 
            print('Машина с маленьким пробегом')

c1 = Car('Красный', 14000, check_mileage)

c1.check_mileage() # TypeError: check_mileage() missing 1 required positional argument: 'self'

c1.check_mileage(c1) # Машина с большим пробегом

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

В книге нет примера с методами. Можно ли написать так, чтобы self не передавать каждый раз?

Ответы

▲ 6Принят

Рабочий вариант - отнаследоваться от созданного namedtuple с добавлением своего метода:

from collections import namedtuple


class Car(namedtuple('Авто' , 'color mileage')):
    def check_mileage(self): 
        if self.mileage > 10000: 
            print('Машина с большим пробегом')
        else: 
            print('Машина с маленьким пробегом')


c1 = Car('Красный', 14000)

c1.check_mileage()

Также можно использовать "новый" (c Python 3.6) NamedTuple с объявлением в стиле датаклассов, сразу объявить класс с нужным методом:

from typing import NamedTuple


class Car(NamedTuple):
    color: str
    mileage: int

    def check_mileage(self): 
        if self.mileage > 10000: 
            print('Машина с большим пробегом')
        else: 
            print('Машина с маленьким пробегом')


c1 = Car('Красный', 14000)

c1.check_mileage()