python类方法中的self关键字使用

 更新时间:2023年12月27日 10:15:05   作者:m0_38063172  
这篇文章主要介绍了python类方法中的self关键字使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

之前学python爬虫的时候要把函数封装到类里面,写成类方法,知道在python的类方法中第一个参数应该是self,但对self代表的具体意义不甚了了。

最近在看Java,对面向对象编程的了解更多了一点,终于彻底弄明白self到底是什么了。

Python的类

在python中,所有的类都直接或间接继承自Object类,定义了类之后就定义了一个命名空间,里面定义的属性可以通过类名来引用。

新定义的类中有一些Object中有的属性,可以在其中定义其他变量或者函数。实例化之后会创建一个对象,该对象脱胎于类,并且其中的属性动态地和类中的属性产生关联:

class A:
    pass
   
a = A()

这段代码创建了一个类A,并且对它进行了实例化,实例化之后的对象绑定为变量a。

我可以看看A里面和a里面分别有什么:

In [38]: dir(A)
Out[38]:
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__']
In [39]: dir(a)
Out[39]:
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__']

用dir函数输出A中和a中的属性后,我们可以看到A和a中的属性是一样的。

我们可以向其中添加属性,添加属性时必须初始化:

In [40]: A.b
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-40-ebcfc7dbf31a> in <module>()
----> 1 A.b

AttributeError: type object 'A' has no attribute 'b'
In [41]: A.b = 1

现在我们可以看看A和a中的属性发生了什么变化:

In [42]: dir(A)
Out[42]:
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'b']
In [43]: dir(a)
Out[43]:
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'b']
In [74]: A.b
Out[74]: 1

In [75]: a.b
Out[75]: 1

我们可以看到,在A中和它的实例化对象中现在都有了属性b,而且它们的值相等。

如果我们给A的实例化对象中添加属性呢:

In [44]: a.c = 2

In [45]: hasattr(a, c)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-45-15d927c71e90> in <module>()
----> 1 hasattr(a, c)

NameError: name 'c' is not defined

竟然报错了,c没有定义,报错的原因是A的实例化对象a的命名空间中有c,但是公共命名空间中没有c,所以我们再试一次:

In [58]: c = a.c

In [59]: hasattr(a, 'c')
Out[59]: True

In [60]: hasattr(A, 'c')
Out[60]: False

我们可以看到,a中有c,但是A中并没有c。是不是因为c指向的是a.c所以A中没有呢:

In [61]: b = a.b

In [62]: hasattr(A, 'b')
Out[62]: True

确实是因为在类的实例化对象中添加的属性不会加入类中。

我们接着看给A或a中加入函数属性会发生什么:

In [78]: A.foo = lambda x : x + 1

In [79]: A.foo(1)
Out[79]: 2

In [80]: a.foo(1)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-80-7dc85fd7a693> in <module>()
----> 1 a.foo(1)

TypeError: <lambda>() takes 1 positional argument but 2 were given

python方法函数中的self关键字

上面执行"a.foo(1)"语句时有个报错,说只需要一个参数,但是给了两个参数,这第二个参数是怎么来的,为什么A.foo(1)就不会出错。

这里我们可以引出python类中的方法函数,方法函数指的是通过类的实例化对象调用的函数,方法函数的第一个形参表示类的实例化对象,通常写成self。

执行a.foo(1)时就相当于执行A.foo(a,1),因为A.foo()中只有一个形参,传入的参数多于需要的参数,所以发生类型错误。

我们在A的定义中重新定义foo:

class A:
    def foo(self, n):
        print(n+1)
   
a = A()

现在我们在a中调用foo就不会有问题了:

In [85]: a.foo(1)
2

我们也可以试试调用A.foo:

In [86]: A.foo(a, 1)
2

总结

python的类中定义函数时的self关键字跟python的方法函数有关,方法函数由类的实例化对象调用,需要把调用它的实例化对象传入方法函数中,self即是表示实例化对象的形参。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 使用Python程序抓取新浪在国内的所有IP的教程

    使用Python程序抓取新浪在国内的所有IP的教程

    这篇文章主要介绍了使用Python程序抓取新浪在国内的所有IP的教程,作为Python网络编程中获取IP的一个小实践,需要的朋友可以参考下
    2015-05-05
  • 利用Opencv中Houghline方法实现直线检测

    利用Opencv中Houghline方法实现直线检测

    这篇文章主要为大家详细介绍了利用Opencv中的Houghline方法进行直线检测,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02
  • Python字符与ASCII码相互转换方法

    Python字符与ASCII码相互转换方法

    在做python编程时,碰到了需要将字母转换成ascii码的需求,所以下面这篇文章主要给大家介绍了关于Python字符与ASCII码相互转换的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-06-06
  • 解决python -m pip install --upgrade pip 升级不成功问题

    解决python -m pip install --upgrade pip 升级不成功问题

    这篇文章主要介绍了python -m pip install --upgrade pip 解决升级不成功问题,需要的朋友可以参考下
    2020-03-03
  • itchat接口使用示例

    itchat接口使用示例

    这篇文章主要介绍了itchat接口使用示例,itchat接口的相关知识,这里是一段代码示例,这里分享给大家,供需要的朋友参考。努力学习中~
    2017-10-10
  • Python调用Fortran的三种形式

    Python调用Fortran的三种形式

    这篇文章主要介绍了在Python中调用Fortran的三种形式,文中有详细的代码示例,感兴趣的同学可以参考阅读
    2023-04-04
  • python实现网页录音效果

    python实现网页录音效果

    这篇文章主要为大家详细介绍了python实现网页录音效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-10-10
  • python语法学习print中f-string用法示例

    python语法学习print中f-string用法示例

    这篇文章主要为大家介绍了python语法学习print中f-string用法示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • Python多线程及其基本使用方法实例分析

    Python多线程及其基本使用方法实例分析

    这篇文章主要介绍了Python多线程及其基本使用方法,结合实例形式分析了Python相关概念、原理、使用方法及操作注意事项,需要的朋友可以参考下
    2019-10-10
  • pytest多线程与多设备并发appium

    pytest多线程与多设备并发appium

    这篇文章介绍了pytest多线程与多设备并发appium,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06

最新评论