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
学习计划 – 第 7 页 – 煅魂-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。

pycharm的debug功能原来这么好用

大部分程序猿都知道,不管是开发新功能还是修复BUG,其实真正写代码的时间是非常少,因为大部分的时间都是消耗在了运行/测试也就是调试(debug)上了,所以掌握快捷高效的调试方法将会让你事半功倍。

PyCharm是由JetBrains公司开发的Python集成开发环境(IDE),凭借其强大的调试功能而广受欢迎。今天将详细介绍PyCharm的调试功能,非常简单又好用。

PyCharm调试功能简介

PyCharm提供了多种强大的调试工具,它让我们能够清楚了解代码每一步是怎么运行的,尤其是对新手或者对熟悉新项目的非常友好和有效。调试(debug)功能其中包含自定义命令断点设置调试控制变量监控表达式评估日志点条件断点

接下来以使用python http库请求百度首页的一个简单脚本来展示调试(debug)功能使用过程。

自定义命令

打开调试(debug)配置,点击“+”创建一个新的调试(debug),或者对一个已经存在的配置进行修改

这个面板支持以下重要的配置修改:

  • python环境版本
  • 脚本文件路径,每个调试都可以指定不同的脚本
  • 脚本参数
  • 脚本所运行目录
  • 运行脚本时的环境变量,这在本地调试非常方便,可以用于区别线上生产环境

修改完之后,点击应用(apply)和保存(save)来应用这些配置,当你点击调试(debug)时这些面板参数组成一个shell命令进行执行,类似于

python xxxx.py --abc -def 123

设置断点

首先,打开需要调试的Python文件。在代码编辑器中,单击行号旁边的空白区域以设置断点。断点将以红点的形式显示。

启动调试

由于刚刚上面已经面板参数中已经指定了具体的脚本了,所以点击调试(debug)按钮(一个绿色长得像虫子的按钮)就可以开始执行脚本调试了

还一种更快捷的方式启动调试,就是右键单击文件中的代码,然后选择调试文件(Debug ‘filename’)(或通过快捷键Shift + F9)。PyCharm将启动调试会话

使用调试控制选项

一旦程序暂停在断点处,此时PyCharm提供了以下调试控制选项(mac的键位可能有点不一样,以下是window的键位):

继续执行(F9):继续执行代码,直到遇到下一个断点或程序结束,在循环比较多的代码非常好用。
逐步执行(F8):逐行执行代码,并自动进入函数调用,这个在一些复杂的代码里非常好用。
逐步出入函数(Shift + F8):逐步进入或退出函数调用。
逐步进入(F7):逐行执行代码,并进入函数调用。

查看变量和表达式求值

在调试过程中,你可以查看“变量”窗口中的变量值。你还可以在”监视(Watches)“选项卡中添加自定义监视表达式。例子中我们可以清楚看到脚本里每个中间变量如“url”以及一些预测变量如”resp.read().decode(“utf-8”)“。


另外,你可以通过右键单击代码并选择”对表达式求值(Evaluate Expression)“来评估表达式。输入表达式并查看结果。

这个功能可以代替平常临时用print去打印一些脚本中间变量的用法,而且也不会产生忘记删除print留下无用日志之类的后遗症,让自己能更加清晰的看到一些中间变量的数据结构逻辑处理过程。

设置日志点和条件断点

在调试过程中,你可以通过右键单击断点并选择”编辑(Edit breakpoint)“来设置日志点和条件断点。输入条件表达式或日志消息,然后保存。比如下面这个设置了只有请求为200时才会触发断点,其他情况则会跳过不触发。

四、总结
PyCharm提供了全面而强大的调试工具,使得调试Python代码变得更加容易和高效。通过熟练掌握这些功能,你可以更快地找到代码中的问题并进行修复,提高开发和调试效率。你学会了吗?