关于Python的前后、单双下划线作用,看完这篇文章吊打面试官!

简介: 在Python中,可能最常见的就是各种常量、变量、函数、方法前后添加的那些下划线了。有前面加的、后面加的,加一个的,加两个的,看到头晕。那么,你对这些知识都掌握了吗 ?让我们先来做一个自测吧。

python的各种下划线


在Python中,可能最常见的就是各种常量、变量、函数、方法前后添加的那些下划线了。有前面加的、后面加的,加一个的,加两个的,看到头晕。那么,你对这些知识都掌握了吗 ?让我们先来做一个自测吧。

题目:说明以下四个例子输出的结果分别是什么。

网络异常,图片无法展示
|

自测题

各位,请开始你的表演,来看看以上4段代码分别输出的结果是什么?OK,记住你的答案,等看完文章解开谜底后,再来看看的答对了没。


单前导下划线


单前导下划线(_xxx),作为Python的命名约定,表示仅供内部使用。但注意这个命名约定,在类中你使用单前导线声明的变量,依然可以在外部直接访问。那这种命名约定还有什么意义呢?有!当代码使用from modlue import * 导入某个模块时,单前导线这种定义方式的属性,不会被导入。举例:

# demo1.py
Name = "清风"
_Age = 18
# demo2.py
from demo1 import *
print(print(Name,_Age))
#output:
NameError: name '_Age' is not defined

正常的情况是如上结果,但是万事无绝对,面试官的阴人考点来了:

__all__ = ["Name", "_Age"]

demo1.py在开头声明如上,使用__all__单独声明了可导入内容时,可以正常导入。虽然使用起来矛盾,但是面试阴人必备有木有?


单末尾下划线


单末尾下划线(xxx_),按照PEP8规定,单末尾下划线也是一个约定 用来避免与python关键字产生命名冲突。

例如:我们使用Beautifulsoup进行网页解析,通过类方法定位时,会找某个标签它的存在class=‘xxx’的情况,此时css的class与Python中的类重名,需要在class后添加单下划线进行区分。类似场景还有很多,就不一一列举了。


双前导和双末尾下划线


日常开发中,最好避免在自己的程序中使用以双下划线(“dunders”)开头和结尾的名称,因为它是Python语言定义的一种特殊方法(魔法方法),我们熟知的__init__ 、__dict__ 、__getitem__等等。

但是,如果你非要使用这种写法去声明,那可真是无底坑...如果你声明的变量不是内置的魔法方法,Python会将它当做普通的变量来操作。如果和内置的方法重名,要么重写,要么因为功能冲突而引发报错,所以不作死就不会死,还是别这么玩了。


双前导下划线


这个为什么放在最后,因为压轴啊!双前导下划线,在面试中被考到的几率太大了,尤其是那种长相猥琐,心术不正的面试官,最爱问这个知识点,所以要牢记。

首先双前导下划线(__xxx)的命名,90%情况下是真切的私有变量、方法。剩下10%一会儿再说。下来说说双前导下划线的作用,既然为私有属性,那么仅在当前类中可用,外部、子类均无法调用和继承。知道这点写代码差不多够了,但还差一点,拿文章开头的最后一个例子来说

# Test4
class Root:
    def __func(self):
        print('root')
class Child(Root):
    def __init__(self):
        self.__func()
Child()

大家刚才的答案是什么,root?恭喜你,打错了,结果是:

AttributeError: 'Child' object has no attribute '_Child__func'

不该是子类没有的方法,继承父类么,命名父类有,为什么会报错。刚才我们说到了,双前导下划线是真切的私有变量、方法,无法被子类所继承。如果我们把双前导下划线,变成了单前导下划线(如Test3),那么结果是root。

不能继承的问题明白了,但这个_Child__func是什么鬼?这就要说为什么刚才我说双前导下划线90%的情况下是真切的私有变量了、让我们来看下面的例子:

class Demo:
    def __init__(self):
        self.__name = "清风Python"
    def __say_hello(self):
        print(f"你好:{self.__name}")
D = Demo()
# usually
print(D.__name)
D.__say_hello
# specially
print(D._Demo__name)
D._Demo__say_hello()

我们定义一个Demo类,其中存在双前导下划线的__name __say_hello,当我们使用通常的调用方式时,时无法执行的,但Python的私有属性声明时,其实就是将某个私有属性前添加单下划线+类名,所以如果其实不存在什么私有属性,我们可以通过_classname__privatefunc的方式实现强制调用。

那么,日常中我们能否尽量的避免这种方式呢?方法是有的,但是只能骗骗初学者,对有心人还是没用,比如:

class Demo:
    def __init__(self):
        self.__money = 100
    @property
    def money(self):
        return self.__money
    @money.setter
    def money(self, pwd):
        pass
D = Demo()
D.money = 1000000
print(D.money) # 依旧为100块

python的property装饰器,可以将方法声明为类的属性,当某人调用D.money得到自己余额为100块时,肯定想着我重新赋值余额秒变土豪,但真实的余额我们使用的是私有的self.__money。而通过property创建了一个money的属性,当用户对money赋值时,money.setter的方法是空的,你怎么赋值都是无用的(空的干嘛还要写,因为不写会报错啊...AttributeError: can't set attribute)。

这样看起来很完美啊,为什么说只能骗骗初学者?当你打印print(D.__dict__){'_Demo__money': 100}一目了然。

最后,文章开头的测试题答案你做对了么?结果是:

child、root、root、报错

今天关于Python中下划线的内容就到此为止,是否起到了稳固执行的效果呢?如果觉得有所收获,欢迎分享给你的小伙伴们一起进步啊!


The End



相关文章
|
2月前
|
JSON Linux 数据格式
Python模块:从入门到精通,只需一篇文章!
Python中的模块是将相关代码组织在一起的单元,便于重用和维护。模块可以是Python文件或C/C++扩展,Python标准库中包含大量模块,如os、sys、time等,用于执行各种任务。定义模块只需创建.py文件并编写代码,导入模块使用import语句。此外,Python还支持自定义模块和包,以及虚拟环境来管理项目依赖。
Python模块:从入门到精通,只需一篇文章!
|
5月前
|
Python
揭秘Python编程核心:一篇文章带你深入掌握for循环与while循环的奥秘!
【8月更文挑战第21天】Python中的循环结构——for循环与while循环,是编程的基础。for循环擅长遍历序列或集合中的元素,如列表或字符串;而while循环则在未知循环次数时特别有用,基于某个条件持续执行。本文通过实例展示两种循环的应用场景,比如用for循环计算数字平方和用while循环计算阶乘。此外,还通过案例分析比较了两者在处理用户输入任务时的不同优势,强调了根据实际需求选择合适循环的重要性。
59 0
|
2月前
|
测试技术 开发者 Python
对于Python中的异常要如何处理,raise关键字你真的了解吗?一篇文章带你从头了解
`raise`关键字在Python中用于显式引发异常,允许开发者在检测到错误条件时中断程序流程,并通过异常处理机制(如try-except块)接管控制。`raise`后可跟异常类型、异常对象及错误信息,适用于验证输入、处理错误、自定义异常、重新引发异常及测试等场景。例如,`raise ValueError("Invalid input")`用于验证输入数据,若不符合预期则引发异常,确保数据准确并提供清晰错误信息。此外,通过自定义异常类,可以针对特定错误情况提供更具体的信息,增强代码的健壮性和可维护性。
|
3月前
|
机器学习/深度学习 算法 Java
机器学习、基础算法、python常见面试题必知必答系列大全:(面试问题持续更新)
机器学习、基础算法、python常见面试题必知必答系列大全:(面试问题持续更新)
|
3月前
|
编解码 UED Python
Python批量修改指定目录下图片的大小名文章
Python批量修改指定目录下图片的大小名文章
22 1
|
4月前
|
存储 Go C语言
Python 的整数是怎么实现的?这篇文章告诉你答案
Python 的整数是怎么实现的?这篇文章告诉你答案
72 7
|
4月前
|
JSON API 数据库
从零到英雄?一篇文章带你搞定Python Web开发中的RESTful API实现!
在Python的Web开发领域中,RESTful API是核心技能之一。本教程将从零开始,通过实战案例教你如何使用Flask框架搭建RESTful API。首先确保已安装Python和Flask,接着通过创建一个简单的用户管理系统,逐步实现用户信息的增删改查(CRUD)操作。我们将定义路由并处理HTTP请求,最终构建出功能完整的Web服务。无论是初学者还是有经验的开发者,都能从中受益,迈出成为Web开发高手的重要一步。
68 4
|
3月前
|
Java C++ Python
【面试宝典】深入Python高级:直戳痛点的题目演示(下)
【面试宝典】深入Python高级:直戳痛点的题目演示(下)
|
4月前
|
Java 程序员 API
Python中的单下划线和双下划线使用规则
Python中的单下划线和双下划线使用规则
44 11
|
3月前
|
存储 自然语言处理 数据库
Python字典操作实现文章敏感词检索
Python字典操作实现文章敏感词检索
37 0