python __new__ __init__ __call__详解

本文详细解析了Python中对象的创建过程,包括__new__、__init__及__call__方法的作用和区别。通过示例展示了如何自定义这些方法来实现特定的功能。
new
  • __new__(cls, *args, **kwargs)
  • 创建一个实例(通常是cls的,也可以是其他类型的实例)
init
  • __init__(self, *args, **Kwargs)
  • 在实例被new创建后,返回给调用者前被执行

  • 如果new返回的是cls的实例,那么init方法会被自动执行,self是创建的实例,init的入参和new的入参是一样的

    If new() returns an instance of cls, then the new instance’s init() method will be invoked like init(self[, …]), where self is the new instance and the remaining arguments are the same as were passed to new().

  • 如果new返回的不是cls的实例,那么init方法不会被执行

    If new() does not return an instance of cls, then the new instance’s init() method will not be invoked.

  • new用于继承不可变类型,创建自定义的实例;也可以用来在自定义的元类中重写,创建自定的实例

    new() is intended mainly to allow subclasses of immutable types (like int, str, or tuple) to customize instance creation. It is also commonly overridden in custom metaclasses in order to customize class creation.

call
  • __call__(self, *args, **Kwargs)
  • 创建好的实例被调用时,触发;举个栗子,实例instance,执行instance()会触发call
  • 即允许一个类的实例,可以像函数一样被调用
示例代码
  • new返回类自己的实例
class Bar(object):
    pass
class Foo(object):
    def __new__(cls, *args, **kwargs):
        print 'foo new'
        print 'args {}'.format(args)
        print 'kwargs {}'.format(kwargs)
        return super(Foo, cls).__new__(cls, *args, **kwargs)
    def __init__(self, *args, **kwargs):
        print 'foo init'
        print 'args {}'.format(args)
        print 'kwargs {}'.format(kwargs)
    def __call__(self, *args, **kwargs):
        print 'foo call'
        print 'args {}'.format(args)
        print 'kwargs {}'.format(kwargs)
foo = Foo('a', 1, other=['id', 'ip'])
foo(1, 2, 3, other=['a', 'b'])

foo new
args (‘a’, 1)
kwargs {‘other’: [‘id’, ‘ip’]}
foo init
args (‘a’, 1)
kwargs {‘other’: [‘id’, ‘ip’]}
foo call
args (1, 2, 3)
kwargs {‘other’: [‘a’, ‘b’]}

  • new不返回实例(init不会被执行, call被调用会报错)
# coding: utf-8
class Bar(object):
    pass
class Foo(object):
    def __new__(cls, *args, **kwargs):
        print 'foo new'
        print 'args {}'.format(args)
        print 'kwargs {}'.format(kwargs)
        # return super(Foo, cls).__new__(cls, *args, **kwargs)
    def __init__(self, *args, **kwargs):
        print 'foo init'
        print 'args {}'.format(args)
        print 'kwargs {}'.format(kwargs)
    def __call__(self, *args, **kwargs):
        print 'foo call'
        print 'args {}'.format(args)
        print 'kwargs {}'.format(kwargs)
foo = Foo('a', 1, other=['id', 'ip'])
# foo(1, 2, 3, other=['a', 'b']) # NonType object is not callable

foo new
args (‘a’, 1)
kwargs {‘other’: [‘id’, ‘ip’]}

  • new返回其他类型的实例(init不会被执行,call调用的是被返回的这个实例的)
# coding: utf-8
class Bar(object):
    def __call__(self, *args, **kwargs):
        print 'bar call'
class Foo(object):
    def __new__(cls, *args, **kwargs):
        print 'foo new'
        print 'args {}'.format(args)
        print 'kwargs {}'.format(kwargs)
        return Bar()
    def __init__(self, *args, **kwargs):
        print 'foo init'
        print 'args {}'.format(args)
        print 'kwargs {}'.format(kwargs)
    def __call__(self, *args, **kwargs):
        print 'foo call'
        print 'args {}'.format(args)
        print 'kwargs {}'.format(kwargs)
foo = Foo('a', 1, other=['id', 'ip'])
foo(1, 2, 3, other=['a', 'b'])

foo new
args (‘a’, 1)
kwargs {‘other’: [‘id’, ‘ip’]}
bar call

  • 在继承不可变类型时newinit的区别
# coding: utf-8
class Foo(int):
    def __init__(self, *args, **kwargs):
        super(Foo, self).__init__(100)
foo = Foo(1)
# 在init中无法修改
print foo

1

# coding: utf-8
class Foo(int):
    def __new__(cls, *args, **kwargs):
        return super(Foo, cls).__new__(cls, 100)
foo = Foo(1)
# 在new中可以修改
print foo

100

  • 在元类编程中new的使用(元编程相关,之后会单独写一篇)
# coding: utf-8
class Foo(type):
    def __new__(cls, *args, **kwargs):
        ret = super(Foo, cls).__new__(cls, *args, **kwargs)
        return ret
class Bar():
    __metaclass__ = Foo
bar = Bar()
print bar
<think>我们正在讨论Python中的`__call__`方法。`__call__`是一个特殊方法(也称为魔法方法),它允许一个类的实例像函数一样被调用。当你调用一个实例时,Python会自动调用该实例的`__call__`方法。 ### 用法说明: 1. **基本语法**: ```python class Example: def __call__(self, *args, **kwargs): # 实现调用逻辑 print("Called with arguments:", args, kwargs) ``` 2. **调用方式**: 创建类的实例后,可以直接用实例名加括号并传入参数来调用`__call__`方法。 ```python e = Example() e(1, 2, 3, a=4, b=5) # 输出: Called with arguments: (1, 2, 3) {'a': 4, 'b': 5} ``` 3. **参数传递**: `__call__`方法可以接受任意数量的位置参数(`*args`)和关键字参数(`**kwargs`),与普通函数相同。 ### 使用场景: - **实现函数对象**:当你希望对象具有函数的行为,但需要维护状态时。 - **装饰器类**:类装饰器通常使用`__call__`来实现装饰逻辑。 - **可调用对象**:需要对象能够被调用,同时保留一些内部状态或配置。 ### 示例代码: 下面是一个简单的计数器类,每次调用都会增加计数: ```python class Counter: def __init__(self): self.count = 0 def __call__(self): self.count += 1 print(f"Current count: {self.count}") # 使用 counter = Counter() counter() # 输出: Current count: 1 counter() # 输出: Current count: 2 ``` ### 注意事项: - 如果类定义了`__call__`,则其实例被称为**可调用对象**(callable)。可以使用`callable()`函数验证: ```python print(callable(counter)) # 输出: True ``` - 未定义`__call__`的实例不可调用,否则会引发`TypeError`。 ### 实际应用案例:类装饰器 ```python class MyDecorator: def __init__(self, func): self.func = func def __call__(self, *args, **kwargs): print("Decorator: before function call") result = self.func(*args, **kwargs) print("Decorator: after function call") return result @MyDecorator def say_hello(name): print(f"Hello, {name}!") say_hello("Alice") ``` 输出: ``` Decorator: before function call Hello, Alice! Decorator: after function call ``` ### 总结: `__call__`方法让对象的行为像函数,为Python对象提供了函数调用的接口。这在需要对象保持状态同时提供函数式接口的场景中非常有用。 §§相关问题§§: 1. 在Python中,如何判断一个对象是否可调用? 2. 除了`__call__`,还有哪些常见的魔法方法(magic methods)? 3. 如何用`__call__`方法实现一个类装饰器? 4. 什么是函数对象(callable object)?它与普通函数有何区别? </think> ### Python中`__call__`的用法详解 `__call__`是Python中的一个特殊方法(魔法方法),它允许类的实例像函数一样被调用。当实例后跟括号`()`时,Python会自动调用该实例的`__call__`方法。 #### 基本用法 ```python class Adder: def __call__(self, a, b): return a + b add = Adder() result = add(3, 5) # 等价于 add.__call__(3, 5) print(result) # 输出: 8 ``` #### 关键特性 1. **使对象可调用**: - 定义`__call__`后,实例会变成可调用对象(callable) - 可用`callable()`函数验证: ```python print(callable(add)) # 输出: True ``` 2. **参数传递**: - 支持任意参数(位置参数、关键字参数) ```python class Greeter: def __call__(self, name, greeting="Hello"): return f"{greeting}, {name}!" greet = Greeter() print(greet("Alice")) # 输出: Hello, Alice! print(greet("Bob", greeting="Hi")) # 输出: Hi, Bob! ``` 3. **状态保持**: - 实例可维护内部状态 ```python class Counter: def __init__(self): self.count = 0 def __call__(self): self.count += 1 return self.count counter = Counter() print(counter()) # 输出: 1 print(counter()) # 输出: 2 ``` #### 实际应用场景 1. **函数装饰器**(类实现): ```python class debug: def __init__(self, func): self.func = func def __call__(self, *args, **kwargs): print(f"调用函数: {self.func.__name__}") return self.func(*args, **kwargs) @debug def say_hello(name): print(f"Hello, {name}!") say_hello("Alice") # 输出: # 调用函数: say_hello # Hello, Alice! ``` 2. **带参数的装饰器**: ```python class repeat: def __init__(self, times): self.times = times def __call__(self, func): def wrapper(*args, **kwargs): for _ in range(self.times): result = func(*args, **kwargs) return result return wrapper @repeat(times=3) def greet(name): print(f"Hello, {name}!") greet("Bob") # 输出: # Hello, Bob! # Hello, Bob! # Hello, Bob! ``` 3. **模拟函数闭包**: ```python class Power: def __init__(self, exponent): self.exponent = exponent def __call__(self, base): return base ** self.exponent square = Power(2) cube = Power(3) print(square(4)) # 输出: 16 print(cube(3)) # 输出: 27 ``` #### 注意事项 - **不可调用对象**:未定义`__call__`的类实例调用时会引发`TypeError` - **优先级**:`__call__`优先级高于普通方法调用 - **性能**:比普通函数调用稍慢,因涉及方法查找
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值