Python 연구 노트 6 : 함수 및 모듈 사용 및 변수 범위에 대한 논의

1. 기능 사용

오늘 저는 Luo Hao의 블로그 게시물을 배우고 그의 관련 지식을 요약했습니다. 도움이 되었으면합니다.
GitHub 원본 링크

  • 求解 :CMN = M! N! (M-N)! , (M = 7, N = 3) C_M ^ N = \ frac {M!} {N! (MN)!}, \ text {(M = 7, N = 3)}미디엄N=N ! ( N ) !M !,(M = 7, N = 3)
m = int(input('m = '))
n = int(input('n = '))
fm = 1
for num in range(1, m + 1):
    fm *= num
fn = 1
for num in range(1, n + 1):
    fn *= num
fmn = 1
for num in range(1, m - n + 1):
    fmn *= num
    
print("求得值为 = {}".format(fm/fn/fmn))

m = 7n
= 3
은 값 = 35.0을 찾습니다.

1.1 기능의 역할

  • 위의 예에서는 세 개의 for 루프를 사용하여 프로그램을 너무 많이 반복했습니다. 프로그래밍 마스터 인 Martin Fowler는 "코드에 악취가 많고 반복이 최악입니다!"라고 말했습니다.
  • 이러한 동일한 기능을 캡슐화하기 위해 문자를 만들어야합니다.

1.2 함수 정의

  • def 키워드를 사용하여 함수 정의
  • 함수가 실행 된 후 return 키워드를 사용하여 수학에서 함수의 종속 변수에 해당하는 값을 반환 할 수 있습니다.
def factorial(num): # factorial:阶乘
    result = 1
    for n in range(1, num + 1):
        result *= n
    return result

m = int(input("m = "))
n = int(input("n = "))

print(factorial(m)/factorial(n)/factorial(m - n))

# 在Python的math模块中已经有一个factorial函数
# 就不需要自己定义函数了

import math

m = int(input("M = "))# 注意要将str强制转换为int
n = int(input("N = "))

c = math.factorial(m)/ \
    math.factorial(n)/ \
    math.factorial(m - n)
print(c)

m = 7n
= 3
35.0
M = 7
N = 3
35.0

위의 함수를 사용하여 정의하면 프로그램이 더 간결하고 간단 해집니다.

1.3 기능 매개 변수

  • 함수의 매개 변수는 기본값을 가질 수 있으며 변수 매개 변수 사용도 지원합니다.
  • 매개 변수 설정은 유연하며 사용 방법이 많습니다.
from random import randint

def rollDice(n = 2):
    """摇色子"""
    total = 0
    for i in range(n):
        total += randint(1, 6)
    return total

def add(a=0, b=0, c=0):
    """三个数相加"""
    return a + b + c

# 如果没有指定参数那么使用默认值摇两颗色子
print(rollDice()) # 4

# 摇三颗色子
print(rollDice(3)) # 14
print(add())       # 0
print(add(1))      # 1
print(add(1, 2))   # 3
print(add(1, 2, 3))# 6

# 传递参数时可以不按照设定的顺序进行传递
print(add(c=50, a=100, b=200))   # 350


1.4 기능 과부하 (동일한 기능을 사용하여 다른 기능을 완료)

  • 위 두 함수의 매개 변수에 대한 기본값을 설정합니다. 즉, 함수 호출시 해당 매개 변수의 값이 전달되지 않으면 매개 변수의 기본값이 사용되므로 위 코드에서 __add__ 함수는 다양한 방식으로 호출 될 수 있으며, 이는 다른 많은 언어에서 함수 오버로딩의 효과와 일치합니다.
  • 위의 __add__ 함수에서 매개 변수 수를 지정했지만 매개 변수 수가 알려지지 않은 경우 어떻게해야합니까?
    • 매개 변수 앞에 *를 추가하여 매개 변수가 변수임을 나타낼 수 있습니다.
def add(*args):
    total = 0
    for i in args:
        total += i
    return total


# 在调用add函数时可以传入0个或多个参数
print(add())          	# 0
print(add(1))			# 1
print(add(1, 2))		# 3		
print(add(1, 2, 3))		# 6


2. 모듈 관리 기능 사용

  • 모든 프로그래밍 언어의 경우 이름 충돌이라는 당혹스러운 상황에 직면하기 때문에 변수 및 함수와 같은 식별자 이름을 지정하는 것은 골치 아픈 일입니다. 가장 간단한 시나리오는 동일한 .py 파일에 동일한 이름의 두 함수를 정의하는 것입니다. Python에는 함수 오버로딩의 개념이 없기 때문에 다음 정의가 이전 정의를 재정의하므로 실제로 동일한 이름을 가진 두 함수가 오직 하나만 존재
  • 간단한 이해는 반복되는 함수 이름이 후자에 의해 덮어 쓰기된다는 것입니다.
def sayHi():
    print("hello")
    return None
    
def sayHi():
    print('hello,world!')
    return None

sayHi()

안녕하세요, 세계!

2.1 위의 문제를 해결하는 방법

  • module1.py, module2.py ...와 같은 각 모듈에 대한 파일을 만듭니다.
  • 모두 다른 파일 (모듈)에서 동일한 이름의 기능이 허용됩니다.
  • 사용할 때 __import__ 키워드를 사용하여 지정된 모듈을 가져옵니다.
from module1 import sayHi

sayHi()

from module2 import sayHi

sayHi()


# 也可以使用下面的方法来区分使用了哪个 sayHi 函数
import module1 as m1
import module2 as m2

m1.sayHi()
m2.sayHi()
  • 코드가 다음과 같이 작성되면 나중에 가져온 sayHi가 이전에 가져온 sayHi를 덮어 쓰기 때문에 마지막으로 가져온 sayHi가 프로그램에서 호출됩니다.
from module1 import sayHi
from module2 import sayHi

sayHi()# 输出hello

from module2 import sayHi
from module1 import sayHi

sayHi()# 输出hello, world!

노트:
  • 우리가 가져 오는 모듈에 함수를 정의하는 것 외에 실행 가능한 코드가 있다면, 파이썬 인터프리터는이 모듈을 가져올 때이 코드를 실행할 것입니다. 사실 우리는 이것을 원하지 않을 수 있으므로 모듈 코드에 실행을 작성하는 것이 가장 좋습니다. 이러한 실행 코드를 아래 표시된 조건에 넣어 모듈이 직접 실행되지 않는 한 if 조건의 이러한 코드는 실행되지 않습니다. 직접 실행되는 모듈 이름 만 "__ main __"이기 때문입니다.
module3.py :
def foo():
    pass


def bar():
    pass


# __name__是Python中一个隐含的变量它代表了: 模块的名字
# 只有被Python解释器直接执行的模块的名字才是: __main__
if __name__ == '__main__':
    print('call foo()')
    foo()
    print('call bar()')
    bar()

foo ()
호출 bar () 호출

import module3

# 导入module3时, 不会执行模块中if条件成立时的代码 
# 因为模块的名字是module3而不是__main__

사례 1 : 최대 공약수와 최소 공배수 계산 기능을 실현

def gcd(x, y):
    
    # 求最大公约数:两个或多个整数共有约数中最大的一个
    # (x, y) = (y, x) if x > y else (x, y)
    for factor in range(y, 0 , -1):
        if x % factor == 0 and y % factor == 0:
            return factor

        
def lcm(x, y):
    # 求最小公倍数
    return x * y // gcd(x, y)


gcd(200, 45)
lcm(7, 7)

사례 2 : 숫자가 회문 번호인지 판단하는 함수 구현

  • 예 : 1234321
def isPal(num):
    temp = num
    total = 0
    while temp > 0:
        total = total * 10 + temp % 10
        temp //= 10
    return total == num

isPal(1234321)


사례 3 : 숫자가 소수인지 판단하는 함수 구현

def isPrime(num):
    # 判断一个数是不是素数
    for factor in range(2, num):
        if num % factor == 0:
            return False
    return True if num != 1 else False
노트:
  • 위의 프로그램에서 알 수 있듯이 코드에서 반복적이고 상대적으로 독립적 인 함수를 함수로 추출 할 때 이러한 함수를 조합하여 더 복잡한 문제를 해결할 수 있다는 것을 알 수 있습니다. 이것이 우리가 함수를 정의하고 사용하는 이유입니다. 매우 중요한 이유입니다.

3. Python의 변수 범위에 관한 문제

  • 변수를 찾을 때의 순서 :
    • 로컬 범위 : c
    • 중첩 된 범위 : b
    • 글로벌 범위 : a
    • 일부 내장 식별자, 입력, 인쇄, int 등과 같은 내장 범위
def foo():
    b = 'hello'  # 局部变量,在foo函数的外部并不能访问到它
                 # 对于foo函数内部的bar函数来说,变量b属于嵌套作用域
                 # 在bar函数中,可以访问到它
    
    # Python中可以在函数内部再定义函数
    def bar():
        
        #nonlocal b
        #b = "nonlocal" # 修改嵌套变量的值
        
        c = True # 局部作用域,在bar函数之外是无法访问
        print(a)
        print(b)
        print(c)

    bar()
    print(b)  
    print(c)     # NameError: name 'c' is not defined

if __name__ == '__main__':
    a = 100      # 全局变量,属于全局作用域
    foo()
    # print(b)   # NameError: name 'b' is not defined

100
안녕하세요
트루
헬로
35.0

# 案例1:
def foo():
    a = 200
    print(a)         # 200


if __name__ == '__main__':
    a = 100
    foo()
    print(a)         # 100
위의 예제를 통해 우리는 a의 최종 출력이 여전히 100임을 알 수 있습니다. python의 검색 순서에 따라 지역 변수가 발견되면 더 이상 다른 변수를 검색하지 않기 때문입니다.
3.1. 전역 변수에서 지역 변수의 값을 사용하려면 다음을 사용할 수 있습니다. global keyword
3.2 함수 내부의 함수가 중첩 된 범위의 변수를 수정할 수 있도록하려면 다음을 사용할 수 있습니다. nonlocal 키워드
# 案例2:
def foo():
    global a
    a = 200
    print(a)  # 200


if __name__ == '__main__':
    a = 100
    foo()
    print(a)  # 200
    

요약하자면 :

  • 실제 개발에서는 글로벌 변수의 범위와 영향이 너무 넓고 예상치 못한 수정 및 사용이 발생할 수 있으므로 글로벌 변수의 사용을 최소화해야합니다. 또한 글로벌 변수는 로컬 변수보다 길어 수명 주기로 인해 메모리가 발생할 수 있습니다. 오랫동안 가비지 수집 이 불가능한 개체가 차지하고 있습니다 .
  • 사실, 전역 변수의 사용을 줄이는 것은 코드 간의 결합 정도를 줄이는 중요한 조치이며 또한 Dimit의 법칙의 실천 이기도 합니다.
  • 전역 변수의 사용을 줄이면 내부 함수에서 변수 범위를 만들어야 하지만 로컬 변수 수명주기 확장을 원하면 결국 함수 호출의 정의를 계속 사용할 수 있습니다. 그 가치, 이번에는 클로저 를 사용해야 합니다.

추천

출처blog.csdn.net/amyniez/article/details/104415925