0

Why does the TypeError message indicate 3 positional arguments if the namedtuple only calls for two? Why does it say that 4 were given?

from collections import namedtuple
Transition = namedtuple('Transition', ('one', 'two'))
a = Transition(1,2,3)
#TypeError: __new__() takes 3 positional arguments but 4 were given
Doug Edmunds
  • 511
  • 3
  • 14
  • 1
    When you call `SomeClass(x, y, z)`, this is sort-of internally translated to `SomeClass.__new__(SomeClass, x, y, z)`. The class is added as an argument (because it may be needed by subclasses in some cases), so the count is one off from what you provide. – Jeremy Feb 05 '19 at 19:24

2 Answers2

1

The first argument on an instance method is always the instance itself (usually named self. Calling Transition(1,2) is Transition.__new__(self, 1, 2).

*Edit: thanks @Slam for pointing out that namedtuple used __new__ instead of __init__

cmccandless
  • 140
  • 10
  • 1
    Almost right, but specifically for `namedtuple` it's question of `__new__`, not `__init__` because of underlying implementation. – Slam Feb 05 '19 at 19:27
  • if there are 4 arguments (1,2,3,4), its reports TypeError: __new__() takes 3 positional arguments but 5 were given And if only 1 argument is given (1), it reports that it is missing 1 required positional argument, not 2 – Doug Edmunds Feb 05 '19 at 19:45
0

Reproduce your mistakes

import collections

# Two-way construct numedtuple
# 1st way:use iterable object as 2nd paras
Transition01 = collections.namedtuple('Transition', ['one', 'two'])
# 2nd way:use space-splited string as 2nd paras
Transition02 = collections.namedtuple('Transition', 'one two')

# In order to figure out the field names contained in a namedtuple object, it is recommended to use the _fields attribute.
print(Transition01._fields)
print(Transition01._fields == Transition02._fields)

# After you know the field name contained in a namedtuple object, it is recommended to initialize the namedtuple using keyword arguments because it is easier to debug than positional parameters.
nttmp01 = Transition01(one=1, two=2)
nttmp02 = Transition01(1, 2)
print(nttmp01)
print(nttmp02)

Debug Info

=======================================

# Transition01(1, 2, 3)
# Traceback (most recent call last):
# TypeError: __new__() takes 3 positional arguments but 4 were given

========================================

Technical details you care about

function namedtuple_Transition.Transition.__new__(_cls, one, two)

Analysis: The named tuple class object you created has an internal implementation method new, and the engineer who defines the method takes the method caller object as the first parameter of the method, and this is a more common class method definition form.

AyiFF
  • 127
  • 1
  • 1
  • 7