-day11 -- function advanced

day11 function advanced

Objective: to master function related fallibility & a necessary skill for project development.

Summary:

  • Supplement of parameters
  • Function name, what is the function name?
  • Distinguish between return value and print.
  • Scope of function

1. Supplement of parameters

Advanced functions can make the code more concise and improve the development efficiency under specific circumstances.

1.1 parameter memory address [interview question]

How to view the address of a value in memory:

# If the contents are the same, the memory addresses are the same
v1 = [11,22,33]
v2 = [11,22,33]

print( id(v1) )
print( id(v2) )
v1 = [11,22,33]
v2 = v1

print( id(v1) )
print( id(v2) )

Remember that when a function passes parameters, it passes a memory address.

def func(data):
    print(data, id(data))  # Page 2067491588304


v1 = "Page"
print(id(v1))  # 2067491588304

func(v1)

Interview question: what are the default parameters passed in Python?

Answer: memory address

This feature of Python parameters has two benefits:

  • Save memory

  • For the contents of variable types and modified elements in functions, all places will be modified. Variable types: list, dictionary, set.

    utilize python Parameter, you can use functions to modify the contents of variable type elements(Process the element of this value),However, the following conditions must be met:
    Conditions to be met at the same time: 1.The parameter is of variable type, list/dict/set 2.And you can only modify the elements inside the function. In case of re assignment or change, the element of this value cannot be modified by using this feature, and can only be re assigned.
    
    # Variable type & internal modification
    def func(data):
        data.append(666)
        
    v1 = [11,22,33]
    func(v1)
    
    print(v1) # [11,22,33,666]
    
    # Special case: variable type & reassignment
    def func(data):
        data = ["Page","alex"]
        
    v1 = [11,22,33]
    func(v1)
    
    print(v1) # [11,22,33]
    
    # Special case: immutable type, internal elements cannot be modified, and can only be re assigned.
    def func(data):
    	data = "alex"
        
    v1 = "Page"
    func(v1)
    

When many other programming languages execute functions, the data will be copied again by default when passing parameters, which will waste memory.

Note: other languages can also pass memory addresses through keywords such as ref.

In python, if you don't want the external variables to be consistent with the variables of the internal parameters of the function, you can choose to copy the external value and pass it to the function.

import copy

# Variable type & internal modification
def func(data):
    data.append(999)

v1 = [11, 22, 33]
new_v1 = copy.deepcopy(v1) # When you copy a copy of data and then modify the element content, only new will be changed_ V1 without changing v1
func(new_v1)

print(v1)  # [11,22,33]

1.2 the return value of the function is the memory address

def func():
    data = [11, 22, 33]
    return data

v1 = func()
print(v1) # [11,22,33]

Execution process of the above code:

  • Execute func function
  • data = [11, 22, 33] create a memory area, store [11, 22, 33] internally, and the data variable points to this memory address.
  • return data returns the memory address pointed to by data
  • v1 receives the return value, so both v1 and data point to the memory address of [11,22,33] (two variables point to this memory, and the reference counter is 2)
  • After the function is executed, the variables inside the function will be released. (that is, delete the data variable and the reference counter of memory address - 1)

So, finally v1 points to the memory address created inside the function.

def func():
    data = [11, 22, 33]
    return data

v1 = func()
print(v1) # [11,22,33]

v2 = func()
print(v2) # [11,22,33]

Execution process of the above code:

  • Execute func function
  • data = [11, 22, 33] create a memory area and store [11, 22, 33] internally. The data variable points to the memory address 1000001110.
  • return data returns the memory address pointed to by data
  • v1 receives the return value, so both v1 and data point to the memory address of [11,22,33] (two variables point to this memory, and the reference counter is 2)
  • After the function is executed, the variables inside the function will be released. (that is, delete the data variable and the reference counter of memory address - 1)

So, finally v1 points to the memory address created inside the function. (memory address of 1000001110 pointed to by v1)

  • Execute the func function again
  • data = [11, 22, 33] recreate a memory area and store [11, 22, 33] internally. The data variable points to the memory address 11111001110.
  • return data returns the memory address pointed to by data
  • v2 receives the return value, so both v1 and data point to the memory address of [11,22,33] (two variables point to this memory, and the reference counter is 2)
  • After the function is executed, the variables inside the function will be released. (that is, delete the data variable and the reference counter of memory address - 1)

So, finally v1 points to the memory address created inside the function. (11111001110 memory address pointed to by v1)

def func():
    data = [11, 22, 33]
    return data

v1 = func()
print(v1, id(v1)) # [11, 22, 33] 2268648061632

v2 = func()
print(v2, id(v2)) # [11, 22, 33] 2852736258240 
# v2 will reassign a new memory address


# If you pass a number or string, its return value is the same. This is because python has an internal caching and resident mechanism. It will think that this kind of string appears very frequently. It will not be newly created in the next execution, but directly reference the last value internally. This is an internal optimization mechanism in python, which leads to it always.
def func():
    data = "xxxx"
    return data

v1 = func()
print(v1, id(v1)) # xxxx 2631189084208

v2 = func()
print(v2, id(v2)) # xxxx 2631189084208

1.3 default value of parameter [interview question]

The probability of this knowledge point appearing in the interview question is relatively high, but it is rarely used in real development.

def func(a1,a2=18):
    print(a1,a2)

Principle: when Python creates a function (not executed), if it finds a default value in the parameter of the function, it will create an area inside the function and maintain the default value.

  • When the executing function does not transfer a value, let a2 point to the address of the value maintained by the function.

    func("root")
    
  • When the function passes a value, a2 points to the address of the newly passed in value.

    func("admin",20)
    

In a specific case [the default parameter value is variable type list/dict/set] & [this value will be modified inside the function], the default value of the parameter has a pit.

  • pit

    # An area will be maintained in the function memory to store this default value, which can only be accessed inside the function
    def func(a1,a2=[1,2]):
        a2.append(666)
        print(a1,a2,id(a2))
    
    # a1=100
    # a2 -> 2371172973248 # a2 points to this memory address. If the data of this memory address changes, all the data pointing to this memory address will change.
    func(100) # 100  [1,2,666]
    
    # a1=200
    # a2 -> 2371172973248
    # Since a2 is not passed, this memory area maintained by memory will be used (at this time, this memory area already stores the [1,2,66] value), and this area will not be recreated every time it is executed, but has been created during function loading, and will not be recreated every time it is executed later, Instead, it will directly use the memory area that has been loaded for the first time. So a2 still points to this address. All the printed results are: 200 [1,26666]
    func(200) # 200 [1,2,666,666]
    
    # a1=99
    # a2 -> 2248262760256
    # Since a2 passes the value, it will no longer point to the memory area maintained, but to the memory area recreated
    func(99,[77,88]) # 66 [77,88,666]
    
    # a1=300
    # a2 -> 2242183248576
    # Since no value is passed, a2 points to the memory area maintained internally
    func(300) # 300 [1,2,666,666,666] 
    
  • Big pit

    # Internally, an area will be maintained to store [1, 2], assuming that the memory address is 1010101010
    def func(a1, a2=[1, 2]):
        a2.append(a1)
        return a2
    
    # a1=10
    # a2 -> 1010101010 # Because no value is passed, it still points to the memory address maintained internally
    # v1 -> 1010101010 # The return value of the return a2 function is the memory address, so it also points to this address
    v1 = func(10)
    print(v1) # [1, 2, 10]
    
    # a1=20
    # a2 -> 1010101010
    # v2 -> 1010101010
    v2 = func(20)
    print(v2) # [1, 2, 10, 20 ]
    
    # Since the value passed by a2 is [11,22], all new memory addresses will be executed, which can be understood as overwriting the default parameters
    # a1=30
    # a2 -> 11111111111        [11, 22,30]
    # v3 -> 11111111111
    v3 = func(30, [11, 22]) # Since there is value transfer, it will point to a new address, assuming: a2 - > 11111111111 
    print(v3) #  [11, 22,30]
    
    # When v2 = func(20) is executed above, the value is already [1,2,10,20]. Since the value is passed to a1 but not a2, all or the address before execution is defaulted, the result is: [1,2,10,20,40] 
    # a1=40
    # a2 -> 1010101010
    # v4 -> 1010101010
    v4 = func(40)
    print(v4) # [1, 2, 10, 20,40 ] 
    
  • Deep pit

    # Create space storage [1, 2] in memory. Assumed address: 1010101010
    def func(a1, a2=[1, 2]):
        a2.append(a1)
        return a2
    
    # a1=10
    # a2 -> 1010101010 # The original memory address is executed without value transfer
    # v1 -> 1010101010
    v1 = func(10) # It only points to the memory address, and there is no print() value
    
    
    # a1=20
    # a2 -> 1010101010 # The original memory address is executed without value transfer
    # v2 -> 1010101010
    v2 = func(20)
    
    # a1=30
    # a2 -> 11111111111  # Since the value is passed, it points to the memory address of the incoming value
    # v3 -> 11111111111 
    v3 = func(30, [11, 22])
    
    # a1=40
    # a2 -> 1010101010 # The original memory address is executed without value transfer
    # v4 -> 1010101010
    v4 = func(40)
    
    print(v1) # [1, 2, 10, 20, 40] 
    print(v2) # [1, 2, 10, 20, 40]
    print(v3)  # v3 Since it is a new address pointing to, the output # [11,22,30]
    print(v4) # [1, 2, 10, 20, 40] 
    #Summary: the data of the address pointed to by v1,v2 and v4 (the address maintained internally before function execution) has changed, so the data of v1,v2 and v4 have also changed
    

1.4 dynamic parameters

Dynamic parameter. When defining a function, use * or * * at the formal parameter position to take any parameter.

def func(*args,**kwargs):
    print(args,kwargs)
    
func("Baoqiang","Jay",n1="tomcat",n2="eric")
# If the parameter is passed through the location, it will be packaged and placed in * args. If the parameter is passed through the keyword, it will be placed under * * kwargs

You can use * and * * when defining a function. In fact, you can also use * when executing a function.

  • The formal parameters are fixed, and the arguments are * and**

    def func(a1,a2):
        print(a1,a2)
        
    func( 11, 22 ) # Position transfer parameter
    func( a1=1, a2=2 ) # Keyword parameters
    
    func( *[11,22] ) # Preceded by *, the elements in the list (or tuple) will be passed to A1 and A2 by position
    func( **{"a1":11,"a2":22} ) # If there are two stars, the dictionary must be used, and then the parameters are passed to a1 and a2 respectively according to the keyword. The output is 11 and 22
    
  • Formal parameters use * and * *, and arguments also use * and * ***

    def func(*args,**kwargs):
        print(args,kwargs)
        
    func( 11, 22 ) # 11 and 22 will be packaged into a tuple, passed to a1 and a2, and an empty dictionary will be output
    func( 11, 22, name="Page", age=18 ) # (11, 22) {'name': 'page', 'age': 18
    
    # Small pit will package "[11,22,33], {"k1":1,"k2":2}" into an element and assign it to * agrs
    func( [11,22,33], {"k1":1,"k2":2} )
    # Output: ([11,22,33], {"k1":1,"k2":2}), {}
    
    
    # args=(11,22,33),kwargs={"k1":1,"k2":2}
    func( *[11,22,33], **{"k1":1,"k2":2} ) 
    
    # It is worth noting that when the data is passed to args and kwargs in this way, the data will be copied again (it can be understood that each element of the internal loop is set in args and kwargs).
    

Therefore, when formatting with format string, you can:

v1 = "I am{},Age:{}. ".format("Page",18)
v2 = "I am{name},Age:{age}. ".format(name="Page",age=18)


v3 = "I am{},Age:{}. ".format(*["Page",18])
v4 = "I am{name},Age:{age}. ".format(**{"name":"Page","age":18})

Exercises

  1. Look at the code writing results

    def func(*args,**kwargs):
        print(args,kwargs)
        
    params = {"k1":"v2","k2":"v2"}
    func(params)    # ({"k1":"v2","k2":"v2"}, ) {}
    func(**params)  # (), {"k1":"v2","k2":"v2"}
    
  2. Read the URL and title in the file, and download the video locally according to the URL (take the title as the file name).

    imitate,https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300f570000bvbmace0gvch7lo53oog&ratio=720p&line=0
     Carter,https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f3e0000bv52fpn5t6p007e34q1g&ratio=720p&line=0
     Ross,https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg&ratio=720p&line=0
    
    # Download video samples
    import requests
    
    res = requests.get(
        url="https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg&ratio=720p&line=0",
        headers={
            "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 FS"
        }
    )
    with open('rose.mp4', mode='wb') as f:
        f.write(res.content)
    
    import requests
    
    def download(title, url):
        res = requests.get(
            url="https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg&ratio=720p&line=0",
            headers={
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36"
            }
        )
        with open('rose.mp4', mode='wb') as f:
            f.write(res.content)
    
    
    with open('db.csv', mode='r', encoding='utf-8') as file_object:
        for line in file_object:
            line = line.strip()
            # print(line)
            row_list = line.split(',')
            # rint(row_list)
            # donload(row_list[0], row_list[1])
    		# It is equivalent to breaking up each list, assigning the first file name to the title on the spot and the url to the url
            download(*row_list)
            
    # Summary: when parameters are passed, one asterisk is passed to args and two asterisks are passed to kwargs
    

2. Function and function name

The function name is actually a variable, which is just a reference to the function.

name = "Page"
def add(n1,n2):
    return n1 + n2

Note: the function must be defined before it can be called and executed (interpretive language: the code is executed from the top and executed while interpreting).

# correct
def add(n1,n2):
    return n1 + n2

ret = add(1,2)
print(ret) 
# error
ret = add(1,2)
print(ret) 

def add(n1,n2):
    return n1 + n2

# Compiled can define functions to the bottom of the executed code

2.1 function as element

Since the function is equivalent to a variable, can the number of rows be regarded as an element in elements such as lists?

def func():
    return 123

data_list = ["Page", "func", func , func() ]

print( data_list[0] ) # String "page"
print( data_list[1] ) # String "func"
print( data_list[2] ) # Function func
print( data_list[3] ) # Integer 123

res = data_list[2]()
print( res ) # Execute the function func and obtain the return value; print and then output the return value.

print( data_list[2]() ) # 123

Note: the function can also be hashed, so the function name can also be used as the element of the collection and the key of the dictionary.

After mastering this knowledge, it is very helpful for subsequent project development. For example, when different operations are performed according to the selection in the project:

  • Scenario 1, for example, to develop a function similar to wechat.

    def send_message():
        """send message"""
        pass
    
    def send_image():
        """Send pictures"""
        pass
    
    def send_emoji():
        """Send expression"""
        pass
    
    def send_file():
        """send files"""
        pass
    
    print("Welcome xx system")
    print("Please select: 1.Send message; 2.Send pictures; 3.Send emoticons; 4.send files")
    choice = input("Enter the serial number of the selection")
    
    if choice == "1":
        send_message()
    elif choice == "2":
        send_image()
    elif choice == "3":
        send_emoji()
    elif choice == "4":
        send_file()
    else:
        print("Input error")
    
    def send_message():
        """send message"""
        pass
    
    
    def send_image():
        """Send pictures"""
        pass
    
    
    def send_emoji():
        """Send expression"""
        pass
    
    
    def send_file():
        """send files"""
        pass
    
    def xxx():
        """Collection"""
        pass
    
    
    function_dict = {
        "1": send_message,
        "2": send_image,
        "3": send_emoji,
        "4": send_file,
        "5": xxx
    }
    
    print("Welcome xx system")
    print("Please select: 1.Send message; 2.Send pictures; 3.Send emoticons; 4.send files")
    choice = input("Enter the serial number of the selection") # "1"
    
    func = function_dict.get(choice)
    if not func:
        print("Input error")
    else:
        # Execution function
        func()
    
    
  • Scenario 2, for example, in a specific situation, it is necessary to send SMS, wechat and e-mail.

    def send_msg():
        """Send SMS"""
        pass
    
    def send_email():
        """Send pictures"""
        pass
    
    def send_wechat():
        """Send wechat"""
        
    # Execution function
    send_msg()
    send_email()
    send_wechat()
    
    def send_msg():
        """Send SMS"""
        pass
    
    def send_email():
        """Send pictures"""
        pass
    
    def send_wechat():
        """Send wechat"""
        pass
        
        
    func_list = [ send_msg, send_email, send_wechat ]
    for item in func_list:
        item()
    

The above two scenarios can only be used when the parameters are the same. If the parameters are inconsistent, errors will occur. Therefore, the program should meet this point during project design. If it cannot be met, other means can be used, such as:

Scenario 1:

def send_message(phone,content):
    """send message"""
    pass


def send_image(img_path, content):
    """Send pictures"""
    pass


def send_emoji(emoji):
    """Send expression"""
    pass


def send_file(path):
    """send files"""
    pass


function_dict = {
    "1": [ send_message,  ['15131255089', 'How do you do']],
    "2": [ send_image,  ['xxx/xxx/xx.png', 'Message content']],
    "3": [ send_emoji, ["😁"]],
    "4": [ send_file, ['xx.zip'] ]
}

print("Welcome xx system")
print("Please select: 1.Send message; 2.Send pictures; 3.Send emoticons; 4.send files")
choice = input("Enter the serial number of the selection") # 1

item = function_dict.get(choice) # [send_message, ['15131255089', 'hello'],
if not item:
    print("Input error")
else:
    # Execution function
    func = item[0] # send_message is equivalent to getting the function name
    param_list = item[1] #  ['15131255089', 'hello'] is equivalent to getting the parameters
 # And because a * is added, the elements of the list will be scattered and the sub table will be passed to the formal parameters of the function   
    func(*param_list) # Send_message (* ['15131255809', 'hello'])

Scenario 2:

def send_msg(mobile, content):
    """Send SMS"""
    pass


def send_email(to_email, subject, content):
    """Send pictures"""
    pass


def send_wechat(user_id, content):
    """Send wechat"""
    pass


func_list = [
    {"name": send_msg, "params": {'mobile': "15131255089", "content": "You have a new message"}},
    {"name": send_email, "params": {'to_email': "wupeiqi@live.com", "subject": "Alarm message", "content": "The hard disk is out of capacity"}},
    {"name": send_wechat, "params": {'user_id': 1, 'content': "wanna a date?"}},
]

#  {"name": send_msg, "params": {'mobile': "15131255089", "content": "you have a new short message"}},
for item in func_list:
    func = item['name'] # send_msg
    param_dict = item['params'] # {'mobile': "15131255089", "content": "you have a new SMS"}
    func(**param_dict) # Send_msg (* * {'mobile': "15131255809", "content": "you have a new SMS"})

2.2 function name assignment

  • Assign a function name to another variable, and the function name is actually a variable, referring to a function; if you assign a function name to another variable, the variable will also refer to the function, for example:

    def func(a1,a2):
        print(a1,a2)
    
    xxxxx = func
    
    # At this time, both xxxxx and func refer to the above function, so they can be executed.
    func(1,1)
    xxxxx(2,2)
    
    def func(a1,a2):
        print(a1,a2)
        
    func_list = [func,func,func]
    
    func(11,22)
    func_list[0](11,22)
    func_list[1](33,44)
    func_list[2](55,66)
    
  • Reassign the function name. If the function name is changed to another value, the function name will no longer refer to the function, for example:

    def func(a1,a2):
        print(a1,a2)
    
    # Execute func function
    func(11,22)
    
    # func is reassigned to a string
    func = "Page"
    
    print(func)
    
    def func(a1,a2):
        print(a1+a2)
        
    func(1,2)
    
    def func():
        print(666)
        
    func()
    

    Note: since the function name will change to the newly defined value after it is redefined, you should not have the same name as the python built-in function when customizing the function, otherwise the functions of the built-in function will be overwritten, for example:

    id,bin,hex,oct,len...
    
    # len built-in function is used to calculate the value length
    v1 = len("Page")
    print(v1) # 2
    
    # len is redefined as another function
    def len(a1,a2):
        return a1 + a2
    
    # When the len function is executed later, it can only be used according to the redefined
    v3 = len(1,2)
    print(v3)
    

2.3 function name as parameter and return value

The function name is actually a variable, which refers to a function. Therefore, like other data types, it can also be used as the parameter and return value of a function.

  • parameter

    def plus(num):
        return num + 100
    
    def handler(func):
        res = func(10) # 110
        msg = "implement func,And the obtained results are:{}".format(res)
        print(msg) # Execute func and get the result: 110
       
    # Execute the handler function and pass plus as a parameter to the formal parameter func of the handler
    handler(plus)
    
  • Return value

    def plus(num):
        return num + 100
    
    def handler():
    	print("implement handler function")
        return plus
        
    result = handler() # Execute the handler function
    data = result(20) # 120
    print(data)
    
    # Execute handler to print out "execute handler function"
    # Execute return plus to point to plus
    # Execute plus(20)
    # Print data 
    

3. Return value and print

For beginners, many people don't know the difference between print and return value, for example:

def add(n1,n2):
    print(n1 + n2)

v1 = add(1,3)
print(v1)

# output
4
None



def plus(a1,a2):
    return a1 + a2

v2 = plus(1,2)
print(v2)
# output
3

The two functions are completely different

  • The use of print in the function is only used to output content at a certain location.
  • Return is used in a function to return the execution result of the function to the caller for subsequent operations.

When calling and executing a function, you should learn to analyze the execution steps of the function.

def f1():
    print(123)


def f2(arg):
    ret = arg() # Equivalent to ret = f1(), 123 is printed after execution, while f1 has no return value, and None is returned by default
    return ret  # Assign None to return, so a None will be returned after f2 is executed
 

v1 = f2(f1)
print(v1)

# output
123
None
# Functions are both parameters and return values
def f1():
    print(123)


def f2(arg):
    ret = arg()  # Execute f1 and output 123. f1 has no return value and returns None by default
    return f1    # Returned the function name of f1


v1 = f2(f1) #  Execute f1 and output 123. f1 has no return value. By default, it returns None. return f1 is not executed

v2 = v1() #Execute f1, output 123, f1 has no return value, return None by default, and execute return f1, so V2 = the return value of v1()
print(v2)

# output
123
123
None

4. Scope

Scope can be understood as a space where data can be shared. Generally speaking, the scope is similar to a house. The things in the house are shared by everyone in it, and the people in other houses can't get them.

4.1 function scope

Python takes * * function * * as the scope, so all data created in the function can be used in this function, but cannot be used in other functions.

def func():
    name = "Page"
    data_list = [11,22,33,44]
    print(name,data_list)
    age = 20
    print(age)

def handler():
    age = 18
    print(age)

func()
handler()

Learn to analyze the code to know which scope the variable belongs to and whether it can be called:

def func():
    name = "Page"
    age = 29
    print(age)
    data_list = [11,22,33,44]
    print(name,data_list)
    
    for num in range(10):
        print(num)
# Function is the scope        
    print(num)
    
    if 1 == 1:
        value = "admin"
        print(value)
	print(value)
    
    if 1 > 2:
        max_num = 10
        print(max_num)
	print(max_num)
    

def handler():
    age = 18
    print(age)

handler()
func()

4.2 global and local

Python takes a function as the scope, and the scope of a function is actually a local scope.

# Stored in global scope
goods = [
    {"name": "computer", "price": 1999},
    {"name": "mouse", "price": 10},
    {"name": "yacht", "price": 20},
    {"name": "beauty", "price": 998}
]
for index in range(len(goods)):
    item = goods[index]
    print(index + 1, item['name'], item['price'])

while True:
    num = input("Please enter the item serial number to be selected(Q/q): ")  # "1"
    if num.upper() == "Q":
        break
    if not num.isdecimal():
        print("The format entered with is incorrect")
        break
    num = int(num)
    send_email()
    if num > 4 or num < 0:
        print("Range selection error")
        break
    target_index = num - 1
    choice_item = goods[target_index]
    print(choice_item["name"], choice_item['price'])
    send_email()
# Global variable (variable name uppercase)
COUNTRY = "China"
CITY_LIST = ["Beijing","Shanghai","Shenzhen"]

def download():
    # local variable
    url = "http://www.xxx.com"
    ...
    
def upload():
    file_name = "rose.zip"
    ...
    

COUNTRY and CITY_LIST is in the global scope. The variables created in the global scope are called global variables, which can be used in the global scope or in its local scope.

The download and upload functions maintain a local scope internally. Variables created in their respective functions are called local variables, and local variables can only be used in this scope. When you want to use a variable in the local scope, the search order is: first search in the local scope; if not, search in the superior scope.

Note: global variables are generally capitalized.

Example 1: read variables of the global scope in the local scope.

COUNTRY = "China"
CITY_LIST = ["Beijing","Shanghai","Shenzhen"]

def download():
    url = "http://www.xxx.com"
    print(url)
    print(COUNTRY)
    print(CITY_LIST)
    
def upload():
    file_name = "rose.zip"
    print(file_name)
    print(COUNTRY)
    print(CITY_LIST)
    
print(COUNTRY)
print(CITY_LIST)
downlowd()
upload()

print(file_name) # report errors
print(url) # report errors

Example 2: local scope and global scope variables have the same name. What is this?

COUNTRY = "China"
CITY_LIST = ["Beijing","Shanghai","Shenzhen"]

def download():
    url = "http://www.xxx.com"
    CITY_LIST = ["Hebei","Henan","Shanxi"]
    print(url)
    print(COUNTRY)
    print(CITY_LIST)
    
def upload():
    file_name = "rose.zip"
    print(COUNTRY)
    print(CITY_LIST)
    
print(COUNTRY)
print(CITY_LIST)
download()
upload()
COUNTRY = "China"
CITY_LIST = ["Beijing","Shanghai","Shenzhen"]

def download():
    url = "http://www.xxx.com"
    CITY_LIST = ["Hebei","Henan","Shanxi"]
    print(url)
    print(COUNTRY)
    print(CITY_LIST)
    
def upload():
    file_name = "rose.zip"
    print(COUNTRY)
    print(CITY_LIST)
    
print(COUNTRY)
print(CITY_LIST)
download()
upload()

COUNTRY = "People's Republic of China"
CITY_LIST = [11,22,33]

download()
upload()

# output
 China
["Beijing","Shanghai","Shenzhen"]
http://www.xxx.com
 China
["Hebei","Henan","Shanxi"]
China
 ["Beijing","Shanghai","Shenzhen"]
http://www.xxx.com
 People's Republic of China
["Hebei","Henan","Shanxi"]
People's Republic of China
[11,22,33]

4.3 global keywords

By default, global variables can only be read and modified in the local scope: internal elements (variable types) cannot be re assigned to global variables.

  • read

    COUNTRY = "China"
    CITY_LIST = ["Beijing","Shanghai","Shenzhen"]
    
    def download():
        url = "http://www.xxx.com"
        print(COUNTRY)
        print(CITY_LIST)
        
    download()
    
  • Modify internal elements (mutable types)

    COUNTRY = "China"
    CITY_LIST = ["Beijing","Shanghai","Shenzhen"]
    
    def download():
        url = "http://www.xxx.com"
        print(CITY_LIST)
        
        CITY_LIST.append("Guangzhou")
        CITY_LIST[0] = "Nanjing"
        print(CITY_LIST)
        
    download()
    
  • A global variable cannot be reassigned in a local variable

    COUNTRY = "China"
    CITY_LIST = ["Beijing","Shanghai","Shenzhen"]
    
    def download():
        url = "http://www.xxx.com"
        # Instead of assigning values to all variables, a local variable city is created in the local scope_ LIST . 
        CITY_LIST =  ["Hebei","Henan","Shanxi"]
        print(CITY_LIST)
    
    def upload():
        file_name = "rose.zip"
        print(COUNTRY)
        print(CITY_LIST)
        
    download()
    upload()
    

If you want to reassign a global variable in a local scope, you can implement it based on the global keyword, for example:

COUNTRY = "China"
CITY_LIST = ["Beijing","Shanghai","Shenzhen"]

def download():
    url = "http://www.xxx.com"
	
    global CITY_LIST
    CITY_LIST =  ["Hebei","Henan","Shanxi"]
    print(CITY_LIST)
    
    global COUNTRY
    COUNTRY = "The People's Republic of China"
    print(COUNTRY)

def upload():
    file_name = "rose.zip"
    print(COUNTRY)
    print(CITY_LIST)
    
download()
upload()

summary

  1. The function parameter passes a memory address.

    • If you want to recreate a copy of the data and pass it to the parameter, you can manually copy one.

    • Special: when a parameter is a dynamic parameter, a data loop will be added to the parameter (similar to copying a copy) when the parameter is transmitted through * or * *

      def fun(*args, **kwargs):
          print(args, kwargs)
      
      
      fun(*[11, 22, 33], **{"k1": 1, "k2": 2})
      
  2. The return value of the function is also the memory address. (after the function is executed, all its internal variables will be destroyed. When the reference counter is 0, the data will also be destroyed.)

    def func():
        name = [11,22,33]
        data = name
        
    func()
    
    def func():
        name = [11,22,33]
        return name
    
    data = func()
    while True:
    	print(data)
    
  3. When the parameter of a function has a default value & the default value is a variable type & the internal elements of the function will be modified (with pits)

    # A list [] is maintained internally, which is always used as long as b does not transfer values.
    def func(a,b=[]):
        b.append(a)
    
  4. * and * * can be used when defining function write form parameters, or when executing functions.

  5. The function name is actually a variable. It can also be used as list, dictionary, collection and other elements (hashable)

  6. The function name can be re assigned, or it can be used as the parameter and return value of another function.

  7. Master the difference between print and return, and learn to analyze the code execution process.

  8. python is function scoped.

  9. When searching for some data in the local scope, give priority to your own. If you don't, search in the superior scope.

  10. Based on the global keyword, you can reassign variables (global variables) in the global scope in the local scope.

Keywords: Python Flask

Added by alfpalafox on Tue, 19 Oct 2021 03:20:45 +0300