程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

What many old drivers dont know -- the meaning of five underscores in Python

編輯:Python

1. Single leading underline :_var (https://jq.qq.com/?_wv=1027&k=aLlhPAxB)

When it comes to variable and method names , A single underscore prefix has a conventional meaning . It's a reminder to programmers - signify Python The community agreed on what it should mean , But the behavior of the program is not affected .

The meaning of the underscore prefix is to inform other programmers : Variables or methods that begin with a single underscore are for internal use only . The agreement is in PEP 8 There are definitions. .

This is not Python Mandatory . Python Unlike Java It's like that “ private ” and “ public ” There are strong differences between variables . It's like someone put forward a small underlined warning sign , say :

“ well , This is not really going to be part of the public interface of the class . Just leave it alone .“—— It's not what the panda said

2. Single end underline var_ (https://jq.qq.com/?_wv=1027&k=aLlhPAxB)

occasionally , The most appropriate name for a variable has been occupied by a keyword . therefore , image class or def Such a name cannot be used as Python Variable name in . under these circumstances , You can attach an underscore to resolve naming conflicts :

>>> def make_object(name, class):
SyntaxError: "invalid syntax"
>>> def make_object(name, class_):
... pass

All in all , Single end underscore ( suffix ) It's an agreement , To avoid contact with Python Keyword naming conflict . PEP 8 Explained the agreement .

3. Double leading underline __var

up to now , The meaning of all naming patterns we are involved in , From an agreed agreement . And for those that start with a double underscore Python Attributes of a class ( Including variables and methods ), It's a little different .

Double underscore prefixes cause Python The interpreter overrides the property name , To avoid naming conflicts in subclasses .

This is also called name modification (name mangling) - The interpreter changes the name of the variable , So that it is not easy to conflict when the class is extended .

I know it sounds abstract . therefore , I combined a small code example to illustrate :

class Test:
def __init__(self):
self.foo = 11
self._bar = 23
self.__baz = 23

Let's use the built-in dir() Function to see the properties of this object :

>>> t = Test()
>>> dir(t)
['_Test__baz', '__class__', '__delattr__', '__dict__', '__dir__',
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'__weakref__', '_bar', 'foo']

The above is a list of the properties of this object . Let's take a look at this list , And look for our original variable name foo,_bar and __baz - I'm sure you'll notice some interesting changes .

self.foo The variable is displayed as unmodified in the attribute list foo.
self._bar They behave the same way - It uses _bar Is displayed on the class . Like I said before , under these circumstances , Leading underscores are just a convention . Just give the programmer a hint .
However , about self.__baz for , It looks a little different . When you search the list __baz when , You won't see a variable with that name .
__baz What happened ?

If you look closely , You will see that there is an object named _Test__baz Properties of . This is it. Python The name modification made by the interpreter . It does this to prevent variables from being overridden in subclasses .

Let's create another extension Test Class in the class , And try to override the existing property added in the constructor :

class ExtendedTest(Test):
def __init__(self):
super().__init__()
self.foo = 'overridden'
self._bar = 'overridden'
self.__baz = 'overridden'

Now? , Do you think foo,_bar and __baz The value of will appear in this ExtendedTest Class ? Let's take a look :

>>> t2 = ExtendedTest()
>>> t2.foo
'overridden'
>>> t2._bar
'overridden'
>>> t2.__baz
AttributeError: "'ExtendedTest' object has no attribute '__baz'"

wait a minute , When we try to see t2 .__ baz The value of , Why do we get AttributeError? The name modifier is triggered again ! The fact proved that , This object doesn't even __baz attribute :

>>> dir(t2)
['_ExtendedTest__baz', '_Test__baz', '__class__', '__delattr__',
'__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__',
'__getattribute__', '__gt__', '__hash__', '__init__', '__le__',
'__lt__', '__module__', '__ne__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',
'__subclasshook__', '__weakref__', '_bar', 'foo', 'get_vars']

As you can see __baz become _ExtendedTest__baz To prevent accidental modifications :

>>> t2._ExtendedTest__baz
'overridden'

But the original _Test__baz still :

>>> t2._Test__baz
42

Double underlined name decoration is completely transparent to programmers . The following example confirms this :

class ManglingTest:
def __init__(self):
self.__mangled = 'hello'
def get_mangled(self):
return self.__mangled
>>> ManglingTest().get_mangled()
'hello'
>>> ManglingTest().__mangled
AttributeError: "'ManglingTest' object has no attribute '__mangled'"

Whether the name modifier also applies to method names ? Yes , Also applicable . Name modification affects the context of a class , With two underscore characters (“dunders”) All names beginning with :

class MangledMethod:
def __method(self):
return 42
def call_it(self):
return self.__method()
>>> MangledMethod().__method()
AttributeError: "'MangledMethod' object has no attribute '__method'"
>>> MangledMethod().call_it()
42

This is another perhaps surprising example of the use of name modifiers :

_MangledGlobal__mangled = 23
class MangledGlobal:
def test(self):
return __mangled
>>> MangledGlobal().test()
23

In this case , I made a statement called _MangledGlobal__mangled Global variable of . Then I was called MangledGlobal Access variables in the context of the class . Because the name modifies , I can be in class test() In the way , With __mangled To quote _MangledGlobal__mangled Global variables .

Python The interpreter automatically changes the name __mangled Expand to _MangledGlobal__mangled, Because it starts with two underscore characters . This indicates that name modifiers are not specifically associated with class properties . It applies to any name that begins with two underscore characters used in the context of the class .

There's a lot to absorb .

honestly , These examples and explanations don't pop out of my mind . I did some research and processing to get it out . I always use Python, For many years , But rules and special situations like this don't always come to mind .

Sometimes the most important skill of a programmer is “ pattern recognition ”, And know where to look up information . If you feel a little overwhelmed at this point , Please don't worry . take your time , Try some examples in this article .

Immerse these concepts completely , So that you can understand the general idea of name modification , And some other behaviors I show you . If one day you meet them by chance , You will know what to look up in the document .

4. Double leading and double trailing underscores var (https://jq.qq.com/?_wv=1027&k=aLlhPAxB)

Perhaps surprisingly , If a name starts and ends with double underscores at the same time , The name modifier is not applied . Variables surrounded by double underlined prefixes and suffixes are not Python Interpreter modification :

class PrefixPostfixTest:
def __init__(self):
self.__bam__ = 42
>>> PrefixPostfixTest().__bam__
42

however ,Python Names with double leading and double trailing underscores are preserved , For special purposes . Examples of this are ,init__ Object constructor , or __call — It allows an object to be called .

these dunder Methods are often called magic methods - but Python Many people in the community ( Including myself ) I don't like this method .

It's best to avoid using double underscores in your own programs (“dunders”) Names at the beginning and end , To avoid the future Python The change of language produces conflict .

5. Underline _ (https://jq.qq.com/?_wv=1027&k=aLlhPAxB)

According to custom , Sometimes a single independent underscore is used as a name , To indicate that a variable is temporary or irrelevant .

for example , In the following loop , We don't need to access running indexes , We can use “_” To indicate that it is just a temporary value :

>>> for _ in range(32):
... print('Hello, World.')

You can also split (unpacking) Use a single underscore as a in an expression “ Don't care ” Variable , To ignore specific values . Again , This meaning is just “ According to the agreement ”, Will not be in Python Trigger special behavior in the interpreter . A single underscore is just a valid variable name , It will only serve this purpose .

In the following code example , I split the car tuple into separate variables , But I'm only interested in color and mileage . however , In order for the split expression to run successfully , I need to assign all values contained in tuples to variables . under these circumstances ,“_” As a placeholder variable, it can come in handy :

'''
No one answers the problems encountered in learning ? Xiaobian created a Python Exchange of learning QQ Group :660193417###
Looking for small partners who share the same aspiration , Help each other , There are also good video tutorials and PDF e-book !
'''
>>> car = ('red', 'auto', 12, 3812.4)
>>> color, _, _, mileage = car
>>> color
'red'
>>> mileage
3812.4
>>> _
12

In addition to being used as a temporary variable ,“_” It's most Python REPL A special variable in , It represents the result of the most recent expression evaluated by the interpreter .

It's very convenient , For example, you can access the results of previous calculations in an interpreter session , perhaps , You are building multiple objects dynamically and interacting with them , There is no need to assign names to these objects in advance :

>>> 20 + 3
23
>>> _
23
>>> print(_)
23
>>> list()
[]
>>> _.append(1)
>>> _.append(2)
>>> _.append(3)
>>> _
[1, 2, 3]

That's all for today's article ~~~ If you think I write well , Can you give me a little praise ? In this way, I will be more motivated ——

I'm a panda , See you in the next article (*◡‿◡)


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved