My Profile Photo

DongChanS's blog


수학과 학생의 개발일지


파이썬 기본 문법 복습(2)


함수의 scope

a=1
def my_func_1():
    a = 5
    my_func_2()
        
def my_func_2():
    print(a, end='')
    
my_func_2() ###############
print(a)
>>> 11

15

  • my_func_2()가 선언되기 전에 호출되었는데?

: 파이썬은 함수에 대해서 약간의 예외를 둔다.

파이썬의 함수호출시점은, 함수를 정의하는 시점이 아니라 실행시점에서 호출을 한다.

즉, ############시점에서는 이미 my_func_2()가 선언되어있으므로 얘를 참고해서 선언할 수 있는 것이다.

비슷하게, 자바스크립트는 컴파일을 하면 정의한 변수와 함수를 전부 올리므로, 함수순서가 의미가 없음.

  • 함수의 Scope : local -> enclosed -> global

    함수 Scope 원칙 : 안에서 밖을 볼 수 있지만, 밖에서 안을 볼 수 없다.

my_func_2()가 my_func_1() 안에서 호출되었지만, 원칙적으로 두 함수는 서로 격리된 scope에 있다.

따라서, my_func_2()에서 a라는 변수가 없다면 enclosed scope는 존재하지 않기 때문에 바로 global scope의 변수를 찾게 되는 것이다.

  • 함수는 Scope를 만든다. 그러나 for나 if는 scope를 만들지 않는다.
for i in [1,2,3]:
    pass
print(i)
>>> 3

c나 java는 for나 if안에 scope를 만들지만, python은 scope를 만들지 않음!

for (int i=0; i<10; i++){
    System.out.println(i)
}
System.out.println(i)
>>> 에러!!
  • closer, generator, 일급 객체로서의 함수(high order function) 을 이해하기 위해서는 위를 이해해야함.
  • 다른 예시 : global에서는 local 내부에 접근할 수 없다!
a=1
def my_func_1():
    a = 5
    my_func_2()
    def my_func_3():
        print(a)
        
my_func_3()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-13-429a6ad74a6a> in <module>()
      6         print(a)
      7 
----> 8 my_func_3()

NameError: name 'my_func_3' is not defined


클래스의 Scope

위에서 for, if문과는 달리 함수는 Scope를 만든다고 하였는데, 클래스 또한 독자적인 scope를 만든다.

ex)

name = 'hong'
class Person:
    name = 'choi'
    def greeting(self):
        print(self.name)
p1 = Person()
p1.greeting()
>>> choi

기본적으로 인스턴스 내에서는 클래스 변수에 접근 할 수는 없다.

하지만, 파이썬은 사용자의 편의를 위하여 인스턴스 내에서 클래스 변수를 볼 수 있게 해놓았다.

그래서, 인스턴스 변수가 정의되지 않았다면, self.name에 아무것도 저장되어있지 않지만, Person.name을 보여주는 것이다.

왜 이러한 기능이 필요한가?

  1. 클래스 변수는 보통 인스턴스들을 관리하기 위하여 선언하는 경우가 많다.
class Person:
    population = 0 # 인스턴스 객체를 카운터하는 역할로 이런걸 씀(인스턴스를 관리하는 정보)
    def __self__(self,name):
        self.name = name
        Person.population += 1
p1 = Person('kim')
p2 = Person('lee')
Person.population
>>> 2

예를 들어서 클래스 전체가 공유하는 클래스변수를 둠으로써 인스턴스 객체를 카운터 할 수 있다.

그리고 이걸 응용해서 학생이라는 평균점수를 업데이트 할 수 있다.

class Student(Person):
    avg = 0 # 처음에는 0이라고 해놓고, 평균점수들을 계속해서 업데이트 할 수 있음.
    sum_score = 0
    def __self__(self,name,score):
        __super__()
        Student.sum_score += score
        Student.avg = Person.sum_score / Person.population
  1. 사람들은 보통 클래스에 직접적으로 접근하지 않는 경우가 많다.

ex) app = Flask() 라고 하면, Flask를 들여다보기보단 app을 들여다보는 경우가 많음(객체로부터 무언가를 작업)

즉, 클래스변수 안에 들어있음직한 변수를 인스턴스에서 쉽게 조회가능함.

클래스 런타임 선언

  1. 변수선언

    파이썬은 유연하기 때문에 인스턴스를 선언한 이후에 멤버변수를 런타임으로 만들 수 있다.

    p1.name = "kim"
    
  2. 메소드선언 : 역시 문제없이 가능함.

    p1.add = lambda x:x
    p1.add('hello')
    >>> 'hello'
    

그러나, 기본적으로 주어진 클래스는 메소드를 편집할 수 없다.

밑에서 소개할 루비라는 언어는 기본적으로 주어진 클래스도 편집할 수 있다.


copy.deepcopy를 직접 구현해보기

"""
[다중리스트의 deepcopy]
이중 리스트라면,
    리스트를 계속 돌면서,
        리스트 안에 리스트가 있다 -> deepcopy를 실행
        리스트가 아니다 -> 그냥 넣어줌.
이중 리스트가 아니라면,
    생성자를 이용해서 shallow copy를 하자.
"""
def is_double(l):
    if type(l) != list:
        return False
    else:
        for value in l:
            if type(value) == list:
                return True
        return False    
def deepcopy(l):
    if is_double(l):
        res = []
        for value in l:
            if type(value) == list:
                res.append(deepcopy(value))
            else:
                res.append(value)
        return res
    else:
        return type(l)(l)
l = [[[1,2,[1,[2,3]]]],1]
l_ = deepcopy(l)

5


**<그외 꿀팁="">**

  • dp- memorization : 작은 문제를 품으로써 점차 큰 문제를 푸는 방식, 재귀함수 필수적임.

이미 푼 문제는 memorization 기법을 통해서 더이상 푸는 수고를 덜음.


  • Scaffold(반복되는 로직을 줄일수 있는 방법)

그것을 빨리 차용한 언어가 레일즈(루비) : 단 4줄 만에 게시판을 만들 수 있다

-> 일단 루비를 이용해서 매우 빠르게 서버사이드를 만들고, 프론트엔드는 다른 언어로 짠 다음에 서비스를

서비스가 잘 되면, 서버사이드를 더 성능이 좋은 언어로 바꾸는 방식으로..

언어의 유연함이 언어마다 다양하게 설정되어있으므로 그걸로 언어사용을 선택할 수 있다.


게다가 루비는 굉장히 유연한 언어임, 루비세상에는 모든게 객체이다.

"hello".upcase
=> "HELLO"

123.to_str
=> "123"

numeric이라는 기본 클래스에 메소드 추가가능(달러화)

class Numeric
    def dollor(X)
        X * 1127
    end
end

200.dolllor(200)
=> 225400


comments powered by Disqus