Python中__init__.py以及__new__() __init__()和__call__()的简单总结

     在实际的NLP项目中,看到了一种标准的封装引用导包和比较常用的类初始化以及魔术函数代码体系,特作总结。

1、__init__.py

看具体的代码包结构:

红色方框中__init__.py的作用是什么呢?

首先看看evaluation包中的__init__.py的内容:

到底起什么样的作用呢?

主要是起到一个简化导包的操作,同时起到一个管理控制的作用。当我们没有在__init__.py做类的初始化的话,在包外应用一些类的时候,代码就要写的很繁杂。图中实例:

需要在mainPackage中调用package1、package2中的类,没有在__init__.py做类的初始化的话就需要些如下代码,同时还可能存在重名问题。

from pythonProjectStrcture.package1.p1class1 import p1class1,whole_name  #手动导包 遇到命名一样的类,和方法就要重命名
from pythonProjectStrcture.package2.walke import walke,whole_name

p1class1('第一', '第二')
p1class1(whole_name)

假如做了初始化的话,就只需要:

from pythonProjectStrcture import package1,package2#使用了__init__.py的作用就很方便的处理导包问题
p1_c1 = package1.p1class1('第一', '第二')
p1_c1.function1('第三')
p1_c2 = package1.p1class2('第四','第五')
p1_c2('key1','key2')

把包引用进来,然后再代码用在引用。这样的好处是,不管函数或者变量是不是重名,都可以调用出来,初始设计类中变量名和方法的时候限制就少一点。以后在做标准的封装的时候,可以考虑这样组织项目结构。

2、__new__() __init__()

这是三个方法是python中比较特殊的方法。

__new__()方法:它的作用就是进行对象的创建,这个差不多是python中最开始调用的方法。

__init__()方法:这个是在对象创建以后进行初始化过程中运行的,作用有点类似JAVA中的getter和setter方法的作用。就是初始化对象的一些属性。

具体的使用看代码:

class p1class1():
    def __init__(self,param1,param2):
        print('进入__init__函数中了')
        self.param1=param1
        self.param2=param2
        self.param3='package1class1的第三个属性'
        print('出__init__函数中了')
    def function1(self,param):
        print('进入function1函数中了')
        print('包1中类1的函数1打印出:',param)
        print('包1中类1的函数1打印出__init__传入的属性:'+ self.param1+self.param2)
        print('包1中类1的函数1打印出__init__写死的属性: '+self.param3)
        print('出function1函数中了')
        return '出function1函数中了'
    def __new__(cls, *args, **kwargs):
        print('进入__new__()函数')
        return super(p1class1,cls).__new__(cls)
if __name__ == '__main__':
    p=p1class1('第一','第二')
    p.function1('第三')

结果输出:

进入__new__()函数
进入__init__函数中了
出__init__函数中了
进入function1函数中了
包1中类1的函数1打印出: 第三
包1中类1的函数1打印出__init__传入的属性:第一第二
包1中类1的函数1打印出__init__写死的属性: package1class1的第三个属性
出function1函数中了

可以看到p=p1class1('第一','第二')代码执行后,最先执行的就是__new__(cls, *args, **kwargs),然后再是__init__(self,param1,param2)函数,最后才是其他的方法。注意到这里的执行顺序,先创建然后再初始化。另外,__new__函数是非必须的,我们自己定义class里面不写__new__方法,对象依然能被创建和初始化,它可以自动被调用。

__new__方法中的参数是cls,而__init__中的是self。当我们自己定义了__new__方法的时候,一定要返回一个super(class,cls).__new__(cls)这样的方法,不然会报错的。如下代码中__new__方法不返回内容就不会执行__init__()方法。

class p1class1():
    def __init__(self,param1,param2):
        print('进入__init__函数中了')
        self.param1=param1
        self.param2=param2
        self.param3='package1class1的第三个属性'
        print('出__init__函数中了')
    def function1(self,param):
        print('进入function1函数中了')
        print('包1中类1的函数1打印出:',param)
        print('包1中类1的函数1打印出__init__传入的属性:'+ self.param1+self.param2)
        print('包1中类1的函数1打印出__init__写死的属性: '+self.param3)
        print('出function1函数中了')
        return '出function1函数中了'
    def __new__(cls, *args, **kwargs):
        print('进入__new__()函数')
if __name__ == '__main__':
    p=p1class1('第一','第二')
    p.function1('第三')
进入__new__()函数
Traceback (most recent call last):
  File "F:/PycharmWorkspace/Python/pythonFundation/pythonProjectStrcture/package1/p1class1.py", line 34, in <module>
    p.function1('第三')
AttributeError: 'NoneType' object has no attribute 'function1'

报错!由于__new__()方法没有返回对象,__init__()方法得不到self的参数,因此__init__方法不执行。

在使用的时候,除非有很强的必要性,都不要自己去重写__new__()方法,一是没必要,二是容易出错。

3、__call__()

这个方法也是比一个特殊但是比较常用的方法,在class对象中写这个方法后,class就变成了callable了。

看代:

class p1class2():
    def __init__(self,param1,param2):
        self.param1=param1
        self.param2=param2
        self.param3='package1class1的第三个属性'
    def function1(self,param):
        print('包1中类2的函数1打印出:',param)
        print('包1中类2的函数1打印出__init__传入的属性:'+ self.param1+self.param2)
        print('包1中类2的函数1打印出__init__写死的属性: '+self.param3)

    def __call__(self,key1,key2):
        print('包1中类2的函数1打印出:__call__ 魔法函数  :%s %s '%(key1,key2))
        return 1



#类外调用

p1_c2 = package1.p1class2('第四','第五')
p1_c2('key1','key2')

结果如下:

进入__new__()函数
进入__new__()函数
包1中类2的函数1打印出:__call__ 魔法函数  :key1 key2 

代码中

p1_c2 = package1.p1class2('第四','第五')

放回的是一个对象,因为写入了__call__()魔法函数,这就使得

p1_c2对象可以像函数一样那要使用,引入自己的参数。
p1_c2('key1','key2')

这样的设计,给编程中带入了很高的灵活性,同时也需要一定的甄辨性。单看p1_c2('key1','key2')你不知道p1_c2是一个函数还是一个对象,就有可能在出现Bug的时候很难找到原因。

参考文章:

https://www.jb51.net/article/147544.htm

详解Python中的__new__、__init__、__call__三个特殊方法(zz) - 很大很老实 - 博客园

### 关于 `rknn_init` 函数的编译错误分析 当遇到 **No matching function for call to rknn_init** 的编译错误时,通常是因为函数签名不匹配或者缺少必要的头文件定义。以下是可能的原因以及解决方案: #### 可能原因 1:参数类型或数量不匹配 如果传递给 `rknn_init` 的参数不符合其声明中的预期,则会引发此错误。可以通过查阅官方文档确认该函数的具体定义。 - 如果使用的是 C++ 调用方式,请确保传入的数据类型已通过 Python/C API 正确转换为对应的 Python 数据结构[^2]。 ```cpp // 假设需要初始化一个字典作为输入参数 PyObject* py_dict = PyDict_New(); // 创建新的字典对象[^3] // 将其他必要参数加入到字典中 PyDict_SetItemString(py_dict, "key", Py_BuildValue("i", value)); // 调用 rknn_init 并传递字典 rknn_ctx ctx; int ret = rknn_init(&ctx, py_dict); ``` 上述代码片段展示了如何利用 Python/C API 构建适合 `rknn_init` 的参数并完成调用过程。 #### 可能原因 2:未包含正确的头文件 确保项目中包含了 RKNN SDK 提供的相关头文件,并链接了所需的库文件。例如,在 CMakeLists.txt 文件中应有如下配置项: ```cmake target_include_directories(your_target PRIVATE ${RKNN_INCLUDE_DIRS}) target_link_libraries(your_target PRIVATE ${RKNN_LIBRARIES}) ``` 此外,还需验证是否正确设置了环境变量 PATH LD_LIBRARY_PATH 来指向 RKNN 库的位置。 #### 可能原因 3:版本兼容性问题 不同版本间的接口可能存在差异。因此建议开发者核对当前使用的 RKNN 版本号及其支持的功能列表,避免因升级而导致原有代码失效的情况发生。 --- ### 总结 针对 “No matching function for call to rknn_init” 错误,需逐一排查以上提到的各种可能性。重点在于核实实际调用形式与目标实现之间的一致性,同时注意开发环境中涉及的所有依赖关系均处于正常状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值