Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the wp-pagenavi domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /var/www/blog.zhujinhui.net/wp-includes/functions.php on line 6114

Notice: 函数 _load_textdomain_just_in_time 的调用方法不正确twentyseventeen 域的翻译加载触发过早。这通常表示插件或主题中的某些代码运行过早。翻译应在 init 操作或之后加载。 请查阅调试 WordPress来获取更多信息。 (这个消息是在 6.7.0 版本添加的。) in /var/www/blog.zhujinhui.net/wp-includes/functions.php on line 6114
面试必问(1):python类的init和new的区别和使用场景 – 煅魂-JeffreyChu的修炼屋

面试必问(1):python类的init和new的区别和使用场景

在 Python 中,__init____new__ 是两个在类的实例化过程中发挥重要作用的方法,但它们各自的作用和使用场景是不同的。

概念区别

__new__

__new__ 是一个静态方法,用于创建实例。它是类的实例化过程中被调用的第一个方法。__new__ 接受类本身(cls)和其他参数,并返回一个实例。一般情况下,除非你有特殊需求,你可能很少需要覆盖 __new__ 方法,写一些底层框架代码的时候可能会用上。

__init__

__init__ 是实例初始化方法。它在 __new__ 创建实例后被调用,用于初始化实例的属性和设置状态。
__init__ 返回 None,它不负责返回实例,也就是说__init__中的self参数其实是__new__方法的返回值。
以下是一个简单示例,展示了__new____init__ 的使用与区别:

class MyClass:
    def __new__(cls, *args, **kwargs):
        print("Calling __new__")
        instance = super(MyClass, cls).__new__(cls)
        # 在这里,你可以控制实例的创建,比如使用单例模式或者工厂模式
        return instance

    def __init__(self, value):
        print("Calling __init__")
        self.value = value

# 创建实例
my_instance = MyClass(42)

# Outputs
# Calling __new__
# Calling __init__

__new__ 方法首先被调用,负责创建实例,然后 __init__ 方法负责初始化实例。

常用使用场景

__new__的使用

new 方法在 Python 中可以用于控制类的实例创建过程,包括实现单例模式工厂模式缓存实例以及预防不合适的实例化等。以下是每个使用场景的代码示例:

单例模式

在单例模式中,__new__ 方法确保类只会有一个实例,并返回同一个实例给每次实例化调用,这个是__new__最常用的场景。

class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super(Singleton, cls).__new__(cls)
        return cls._instance

# 使用示例
s1 = Singleton()
s2 = Singleton()


print(s1 == s2)  # 输出 True,说明两者是同一个实例
工厂模式

在工厂模式中,new 方法可以根据传入的参数返回不同类型的实例。

class AuthStrategy:
    def authenticate(self):
        raise NotImplementedError


class WechatStrategy(AuthStrategy):
    def authenticate(self):
        return "Wechat authenticate"


class EmailStrategy(AuthStrategy):
    def authenticate(self):
        return "Email authenticate"


class AnimalFactory:
    def __new__(cls, auth_type):
        if auth_type == 'wechat':
            return WechatStrategy()
        elif auth_type == 'email':
            return EmailStrategy()
        else:
            raise ValueError("Unknown animal type")


# 使用示例
w = AnimalFactory('wechat')
e = AnimalFactory('email')

print(w.authenticate())  # 输出 "Wechat authenticate"
print(e.authenticate())  # 输出 "Email authenticate"
缓存实例

在缓存实例中,new 方法可以缓存创建的实例,并在重复创建时返回缓存的实例。

class CacheObject:
    _cache = {}

    def __new__(cls, key):
        if key in cls._cache:
            return cls._cache[key]
        else:
            instance = super(CacheObject, cls).__new__(cls)
            cls._cache[key] = instance
            return instance

# 使用示例
obj1 = CacheObject('key1')
obj2 = CacheObject('key1')

print(obj1 == obj2)  # 输出 True,说明两者是同一个实例
预防不合适的实例化

在预防不合适的实例化场景中,new 方法可以通过抛出异常来防止实例化不合适的对象。

class RestrictedInstantiation:
    def __new__(cls, flag):
        if not flag:
            raise ValueError("flag必须为True")
        return super(RestrictedInstantiation, cls).__new__(cls)

# 使用示例
try:
    restricted_instance = RestrictedInstantiation(False)
except ValueError as e:
    print(e)  # 输出 "flag必须为True"

a = RestrictedInstantiation(True)
print("成功创建")  # 这将被打印,因为 flag 是 True

以上示例展示了 __new__ 方法在不同使用场景中的应用,包括单例模式、工厂模式、缓存实例和预防不合适的实例化。

__init__的使用

__init__ 方法在 Python 中用于初始化类的实例。这是类实例化后的第一个方法,它主要用于设置实例的属性和初始化实例的状态,将接下来可能需要的数据或者资源(文件)都准备好。以下是 __init__ 方法的不同使用场景及代码示例:

初始化实例属性

__init__ 方法通常用于初始化实例的属性,以便实例在创建时具备必要的状态。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

# 使用示例
person = Person("Mike", 30)
print(person.name)  # 输出 "Mike"
print(person.age)   # 输出 30
参数验证和处理

__init__ 方法可以用于验证和处理传入的参数,以确保实例属性符合预期。

import re


class Account:
    # 定义正则表达式来验证电子邮件格式
    EMAIL_PTN = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'

    def __init__(self, email):
        if not self.is_valid_email(email):
            raise ValueError("不正确email格式")
        self.email = email

    @staticmethod
    def is_valid_email(email: str) -> bool:
        # 使用正则表达式匹配电子邮件地址
        return re.match(Account.EMAIL_PTN, email) is not None

# 使用示例
try:
    account = Account("111")
except ValueError as e:
    print(e)  # 输出 "不正确email格式"

valid_account = Account("xmishu@xmishu.com")
print(valid_account.email)   # 输出 "xmishu@xmishu.com"
计算派生属性

__init__ 方法可以用于根据输入参数计算派生附加属性,从而在实例创建时提供额外的信息。

class Rectangle:
    def __init__(self, length, width):
        self.length = length
        self.width = width
        self.area = length * width  # 计算面积
        self.perimeter = 2 * (length + width)  # 计算周长

# 使用示例
rect = Rectangle(4, 30)
print(rect.area)      # 输出 120
print(rect.perimeter) # 输出 68

通过这些例子,你可以看到 __init__ 方法在初始化实例属性、验证和处理参数、计算派生属性等场景中的应用。

总结

__new__ 是一个静态方法,用于创建实例(不一定是新的)并返回这个实例;__init__ 是实例初始化方法,设置属性初始状态,它返回的是None。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注