Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the reflection mechanism of python?

2025-04-02 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

What is the reflection mechanism of python? in view of this problem, this article introduces the corresponding analysis and solution in detail, hoping to help more partners who want to solve this problem to find a more simple and feasible method.

Reflection

Reflection mechanism is to dynamically determine the type of object at run time, and can call object properties, methods and import modules through strings. It is a kind of event-driven based on strings.

Interpretive language: the program does not need to be compiled, it is translated into machine language at run time, and it has to be translated every time it is executed. Therefore, the efficiency is relatively low. Compared with the existence of compiled language, the source code is not directly translated into machine language, but first translated into intermediate code, and then interpreted and run by the interpreter. For example, Python/JavaScript / Perl / Shell and so on are all interpreted languages.

Python is an interpreted language, so it supports the reflection mechanism very well. The functions that support the reflection mechanism in python are getattr (), setattr (), delattr (), exec (), eval (), and _ _ import__, which can all execute strings.

Eval

Evaluates the value of the specified expression. It can only execute a single expression, not complex code logic. And it cannot be an assignment expression.

Single expression:

A = "12 + 43" b = eval (a) print (b)

Complex expressions:

A = "print (12 + 43); print (1111)" b = eval (a) print (b) # output: Traceback (most recent call last): File "xxxx.py", line 10, in b = eval (a) File "", line 1 print (12 + 43); print (1111) ^ SyntaxError: invalid syntax

Assignment:

A = 1b = eval ("a = 21") print (b)

Usually when we use eval, we mainly use its return value to get the value calculated by the expression.

Exec

Execute a complex expression and the return value is always None

B = exec ("aa = 21") print (b) # None,exec returns a value that executes an assignment statement for Noneprint (aa) # 21 Magi exec and defines the aa variable

Execute complex statements:

A =''ret = [] for i in range (10): ret.append (I)' 'exec (a) print (ret) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Import module:

# Import module exec ("import config") print (config.KEYWORD) # dynamically create class class Base: def _ _ init__ (self): print ("Base") a = "Base" exec (a + "()")

The ability to import modules is very powerful, so we can create various module classes dynamically.

The difference between the eval () function and exec () function:

The eval () function can only evaluate the value of a single expression, while the exec () function can run code snippets dynamically.

The eval () function can have a return value, while the exec () function always returns a value of None.

Take another look at the following example:

Class Base: def _ init__ (self): print ("Base") def test (self): print ("test") return "Base::test"

What should we do if we want to call the test method of the an object through a string? if you want to get the return value, you can use the

B = eval ("a.test ()") print (b)

Output:

Test

Base::test

If you don't need to get the return value, you can use exec,exec ("a.test ()"), output: test

Although we can use eval and exec to execute the above code, the drawback of this approach is that if this property does not exist, the call will report an error. So what's the way to do it well? First, determine whether the attribute exists. If it exists, call it. If it does not exist, it will not be called. Python provides us with a set of methods: hasattr, getattr, setattr, delattr.

Hasattr

Def hasattr (* args, * * kwargs): # real signature unknown "" Return whether the object has an attribute with the given name. This is done by calling getattr (obj, name) and catching AttributeError. "" Pass

We know from the source code comments that it returns whether the object has the property of the specified name. And it is judged by calling getattr and catching AttributeError exceptions. Just like the property call above, we can use hasattr (a, "test") to determine, through the source code comments, we can also think about whether eval can also implement this method?

Def has_attr (obj, name): try: eval ("obj.%s ()"% name) return True except AttributeError ase: return Falsea = Base () if has_attr (a, "test"): eval ("a.test ()") # output: Basetesttest

But this approach is flawed because test outputs twice, because we call test () twice, which is not what we want. If you use hasattr, this function will not be called once in judgment.

Getattr ()

With a function to determine whether an attribute exists, then there must be a function to get the attribute

Def getattr (object, name, default=None): # known special case of getattr "" getattr (object, name [, default])-> value Get a named attribute from an object; getattr (x,'y') is equivalent to x.y. When a default argument is given, it is returned when the attribute doesn't exist; without it, an exception is raised in that case. "" Pass

From the source code comments, we can know that we can get the property named name of the object object. With object.name, if the default parameter is provided, then the default value will be returned when the property does not exist. It is also the example above:

A = Base () if hasattr (a, "test"): func = getattr (a, "test") func () # output: Basetest

From the example, we can see that hasattr does not call the test function, and getattr gets the function object and does not call it, and we execute the a.test () function through our active execution of func (), which is much more flexible than exec and eval.

Setattr

If you have a property to judge and get, it is also necessary to set the property.

Def setattr (x, y, v): # real signature unknown; restored from _ _ doc__ "" Sets the named attribute on the given object to the specified value. Setattr (x, 'yearly, v) is equivalent to ``x.y = vested' "pass"

Set a special value to the name property of the object object, which is equivalent to x.y = v

Class Base: def _ init__ (self): self.name = "name" a = Base () setattr (a, "name", "zhangsan") print (a.name) # change the value of the original attribute setattr (a, "age", 32) print (getattr (a, "age")) # add a property that does not exist and set the value

Although setattr (a, "age", 32) equals a.age=32, let's not forget that this is an added attribute through a string.

There are judgment, acquisition, addition and, of course, deletion of delattr. We will not elaborate on this. Next we will look at a more important method.

Import

When learning exec, we have an example of importing the configuration file exec ("import config"). Python also provides us with a better way to deal with this way.

Def _ import__ (name, globals=None, locals=None, fromlist= (), level=0): # real signature unknown; restored from _ doc__ "" _ import__ (name, globals=None, locals=None, fromlist= (), level=0)-> module Import a module. Because this function is meant for use by the Python interpreter and not for general use, it is better to use importlib.import_module () to programmatically import a module. The globals argument is only used to determine the context; they are not modified. The locals argument is unused. The fromlist should be a list of names to emulate ``from name import...'', or an empty list to emulate ``import name''. When importing a module from a package, note that _ _ import__ ('A.Bean,...) Returns package A when fromlist is empty, but its submodule B when fromlist is not empty. The level argument is used to determine whether to perform absolute or relative imports: 0 is absolute, while a positive number is the number of parent directories to search relative to the current module. " Pass

The most important thing we need to pay attention to here is the formlist parameter. Let's look at a simple example:

A = _ _ import__ ("config") print (a.KEYWORD)

Config is a py script-config.py, with a variable KEYWORD inside. We need to import this file through other py modules. Using _ _ import__, we can import it as an object and then call it as an object instead of using the exec string all the time. We mentioned above that the parameter formlist needs to be concerned about. Why? We have added a new module: comm. There is a script function.py in the module

# function.pydef comm_function (): print ("test_module")

We now want to call the comm_function function through dynamic introduction, so follow the above method

A = _ _ import__ ("comm.function") a.comm_function ()

Result output:

Traceback (most recent call last): File "xxx.py", line 10, in print (a.comm_function ()) AttributeError: module 'comm' has no attribute' comm_function'

It means that the comm module does not have the attribute comm_function, so why the comm module instead of function? We can print the incoming name of the module print (a. Import name _), and the printed result is comm, which means that we only introduce comm, not function, in the above way. In fact, we know through the source code comments, _ _ import__ (A.B), if fromlist is empty, return package A, if not empty, return its child package B. Modify our code:

A = _ _ import__ ("comm.function", fromlist=True) print (a. Output: comm.functiontest_module

The introduced modules and execution functions are correct and meet our expectations.

Summary

Through the above functions to learn, some of them are commonly used and some are not commonly used, but these functions are essential when we design the framework, especially _ _ import__,. Next we will continue to look at the most important concept in the framework design-metaprogramming. After learning these concepts, you can design the framework. I'm just kidding. It's not that simple. Reading source code is the quickest way to increase knowledge, but the premise is that the foundation must be laid. Otherwise, the source code is confused. After we have sorted out these concepts, we are looking for a few source code libraries to learn the design concepts inside.

This is the answer to the question about the reflection mechanism of python. I hope the above content can be of some help to you. If you still have a lot of doubts to be solved, you can follow the industry information channel to learn more about it.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report