Python 3.6中继承namedtuple时初始化失败问题求助
Hey there! I’ve dealt with my fair share of quirky namedtuple inheritance bugs in Python 3.6, so let’s break down what’s likely going wrong and how to fix it.
First, a quick reminder: namedtuple is a factory function that generates an immutable tuple subclass. Unlike regular classes, it relies on __new__ (not __init__) to create instances, which is where a lot of folks trip up when extending it.
Common Error Scenario 1: Overriding __init__ Incorrectly
If you’re trying to add extra fields or customize initialization by overriding __init__, you’ll almost certainly hit an error. Here’s an example of what not to do:
from collections import namedtuple BaseTuple = namedtuple('BaseTuple', ['a', 'b']) class MyTuple(BaseTuple): def __init__(self, a, b, c): super().__init__(a, b) # This won't work! self.c = c # Calling this triggers a TypeError: __init__() takes 4 positional arguments but 5 were given mt = MyTuple(1, 2, 3)
Fix: Use __new__ Instead
Since namedtuples are immutable, you need to customize instance creation in __new__ (the method that actually constructs the object):
from collections import namedtuple BaseTuple = namedtuple('BaseTuple', ['a', 'b']) class MyTuple(BaseTuple): def __new__(cls, a, b, c): # Create the base namedtuple instance first instance = super().__new__(cls, a, b) # Add your custom attribute (note: this makes the instance technically mutable now) instance.c = c return instance # This works perfectly mt = MyTuple(1, 2, 3) print(mt.a, mt.b, mt.c) # Output: 1 2 3
Common Error Scenario 2: Mismatched Initialization Arguments
If you’re getting a TypeError about wrong number of arguments or unexpected keyword arguments, double-check that you’re passing exactly the fields defined in the parent namedtuple (plus any extras you’ve accounted for in __new__).
For example, this will fail:
BaseTuple = namedtuple('BaseTuple', ['x', 'y']) class MyTuple(BaseTuple): def double_x(self): return self.x * 2 # Error: unexpected keyword argument 'z' mt = MyTuple(x=1, y=2, z=3)
Fix: Align Arguments with NamedTuple Fields
Stick to the fields defined in the parent, or adjust your __new__ to handle extra parameters as shown in the first fix.
Common Error Scenario 3: Using Mutable Default Values
If your parent namedtuple uses mutable defaults (like lists or dictionaries), you’ll run into subtle bugs where all instances share the same mutable object. For example:
# Risky: mutable defaults are shared across instances BaseTuple = namedtuple('BaseTuple', ['a', 'b'], defaults=[[], {}])
Fix: Initialize Mutable Values in __new__
Override __new__ to create fresh mutable objects for each instance:
class MyTuple(BaseTuple): def __new__(cls, a, b=None): if b is None: b = {} # Fresh dict for each instance return super().__new__(cls, a, b)
Final Checks
If you’re still hitting errors, share the exact error message and a snippet of your code—I can help narrow it down further! But chances are, one of these fixes will resolve your initialization issues.
内容的提问来源于stack exchange,提问作者chhenning

