Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way I can change the way list() function works on my class?

Tags:

python

class

I am writing a small class 'AP' ('Arithmetic Progression') for my school assignment. I have included an option for making the AP infinitely long.

class AP:
    def __init__(self, first_term: float, co_diff: float, n: int = inf) -> None:
        self.a1 = first_term
        self.d = co_diff
        self.term = 0
        self.n = n

    def __repr__(self) -> str:
        return f'AP({self.a1}, {self.d}, {self.n})'

    def __str__(self) -> str:
        output_str = f"{', '.join([str(term) for term in list(self.terms(term=6))])}, ...."
        if self.n != inf:
            return output_str + f', {(self.a1 + ((self.n - 1) * self.d))}'
        return output_str

    def terms(self, term: int):
        return AP(self.a1, self.d, n=term)

    def __iter__(self):
        return self

    def __next__(self):
        self.term += 1
        if self.term < self.n:
            return (self.a1 + ((self.term - 1) * self.d))
        raise StopIteration

    def __eq__(self, o: object) -> bool:
        if isinstance(o, AP):
            return str(self) == str(o)

But when someone wants to convert it into a list and if it is an infinite one, I want to raise an error like:

 ValueError: The list() function was called for an object of undefined length.

Same goes for sum() function as well. Are there any solutions to this?

like image 530
NewHere Avatar asked Jun 26 '21 07:06

NewHere


People also ask

Can you turn a function into a list in Python?

Typecasting to list can be done by simply using list(set_name) . Using sorted() function will convert the set into list in a defined order. The only drawback of this method is that the elements of the set need to be sortable.

How does the list function work in Python?

The list() function creates a list object. A list object is a collection which is ordered and changeable.

How do you access a list from another function in Python?

You simply pass a call to function generating your list as an argument (instead of global variable) to a call to function processing the list you want to generate.

How do you create a list inside a function in Python?

Lists in Python can be created by just placing the sequence inside the square brackets[]. Unlike Sets, a list doesn't need a built-in function for its creation of a list. Note: Unlike Sets, the list may contain mutable elements.


1 Answers

A possible trick would be to use the __length_hint__ special method. It is used at least in CPython for all standard conversions of an iterable to a sequence type, and AFAIK should only be used there. You cannot return a value to tell list that the length would be infinite but you can raise the ValueError directly:

def __length_hint__(self):
    if self.n is inf:
        raise ValueError('This object has undefined length.')
    return self.n - 1

Example after adding this method to your class:

>>> ap = AP(1., 1.)
>>> ap
AP(1.0, 1.0, inf)
>>> next(ap)    # iteration is correct
1.0
>>> next(ap)
2.0
>>> next(ap)
3.0
>>> next(ap)
4.0
>>> list(ap)   # list raises ValueError
Traceback (most recent call last):
  File "<pyshell#75>", line 1, in <module>
    list(ap)
  File "<pyshell#68>", line 34, in __length_hint__
    raise ValueError('This object has undefined length.')
ValueError: This object has undefined length.
>>> tuple(ap)     # so does tuple
Traceback (most recent call last):
  File "<pyshell#76>", line 1, in <module>
    tuple(ap)
  File "<pyshell#68>", line 34, in __length_hint__
    raise ValueError('This object has undefined length.')
ValueError: This object has undefined length.
>>> sorted(ap)       # or sorted
Traceback (most recent call last):
  File "<pyshell#77>", line 1, in <module>
    sorted(ap)
  File "<pyshell#68>", line 34, in __length_hint__
    raise ValueError('This object has undefined length.')
ValueError: This object has undefined length.

But as long as you have a finite length, all is fine:

>>> ap = AP(1., 1., 4)
>>> list(ap)
[1.0, 2.0, 3.0]

By the way, you could use the same implementation for the special __len__ method to allow your class to be used by the len builtin function.

like image 101
Serge Ballesta Avatar answered Nov 11 '22 18:11

Serge Ballesta