함수와 클래스

장현빈·2024년 11월 27일

python

목록 보기
3/8

함수(function)

변수가 값에 대한 이름표라면 함수 이름은 코드에 대한 이름표로 파이썬 인터프리터에서 정의한 함수를 실행하면 메모리에 함수 객체를 할당하고 이를 함수이름이 바인딩함.

def hello():
    print("hello")
>>> id(hello)
4751945344
def hello():
    print("hello")
    
f=hello
f()
class Func:
    def __call__(self):
        print('호출 됨')
        
f=Func()
f()

위치인자(*args)

함수를 호출할 때 전달되는 값이 매개변수에 순서대로 전달되는 인자.

def print_number(a,b,c):
    print(a,b,c)

print_number(7,8,9)
#1
print_number(*[7,8,9])
#2
print_number(*(7,8,9))
#3
x=[7,8,9]
print_number(*x)
  • 위치가변인자: *args와 같이 함수 파라미터 앞에 *를 붙여주면 인자값의 개수를 가변적으로 정의 가능.
def foo(*args):
    print(args)
    
foo(1,2,3)
foo(1,2,3,4)
(1, 2, 3)
(1, 2, 3, 4)
  • 키워드가변인자: **kwargs와 같이 함수 파라미터 앞에 ** 를 붙여서 사용함.
def foo(**kwargs):
    print(kwargs)
    
foo(a=1,b=2,c=3)

위치가변인자와 키워드가변인자를 같이쓰는 예시

def foo(*args, **kwargs):
    print(args)
    print(kwargs)
    
foo(1,2,3,a=1,b=1,c=2)

함수 인자로 리스트&튜플 전달

  • 기존 코드
def foo(a, b, c):
    print(a, b, c)
    
data=[1,2,3]
foo(data[0], data[1], data[2])
  • 함수 인자의 개수가 많은 경우에는 인덱싱을 여러번 해줘야 하기 때문에 호출부가 길어지고 코딩해야할 부분이 많아짐. 이럴때는 간단히 함수 호출부에서 리스트나 튜플을 바인딩하는 변수에 *를 붙여주면 됨.
def foo(a, b, c):
    print(a, b, c)
    
data=[1,2,3]
foo(*data)
  • **(더블 아스터리크)
def foo(**kwargs):
    print(kwargs)
  • kwargs는 딕셔너리를 바인딩. kwargs를 출력하면 딕셔너리가 출력됨.
foo(a=1, b=2)
{'a': 1, 'b': 2}

lambda 함수

  • 기존 코드
def mul5(x):
    return 5*x
  • lambda를 사용할 경우 한줄로 줄여서 함수를 생성가능
>>> a=lambda x:5*x
>>> a(2)
10

내장함수

  • abs(x): 어떤 숫자를 입력 받았을때 절댓값을 반환하는 함수
>>> abs(3)
3
>>> abs(-3)
3
>>> abs(-1.2)
1.2
  • all(x): 모든 요소가 참이면 True, 거짓이 하나라도 있으면 False를 반환
>>> all([1,2,3])
True
>>> all([1,2,3,0])
False
>>> all([])
True
  • any(x): 참인 요소가 하나 이상일경우 True, 모두 거짓일 경우 False를 반환
>>> any([1,2,3,0])
True
>>> any([0,""])
False
>>> any([])
False
  • chr(i): 유니코드 숫자 값을 입력받아 그 코드에 해당하는 문자를 리턴하는 함수.
>>> chr(97)
'a'
>>> chr(44032)
'가'
  • dir(): 객체가 지닌 변수나 함수를 보여주는 함수
>>> dir([1,2,3])
'append','clear','copy','count','extend','index','insert','pop', ...
>>> dir({'1':'a'})
'clear','copy','fromkeys','get','items','keys', ...
  • divmod(a, b): 2개의 숫자를 입력받고 나눈 몫과 나머지를 튜플로 반환
>>> divmod(7, 3)
(2, 1)
  • enumerate(): 순서가 있는 데이터(리스트, 튜플, 문자열)을 입력받아 인덱스 값을 포함하는 enumerate 객체를 반환
>>> for i, name, in enumerate(['body', 'foo', 'bar']):
...    print(i, name)
...
0 body
1 foo
2 bar
  • eval(expression): 문자열로 구성된 표현식을 입력받아 해당 문자열을 실행한 결과값을 반환하는 함수
>>> eval('1+2')
3
>>> eval("'hi'+'a'")
'hia'
>>> eval('divmod(4,3)')
(1, 1)
  • filter(func, iterable): 함수와 반복 가능한 데이터를 입력받아 함수를 호출했을때 반환값이 참인 것만 묶어서 반환
def positive(x):
    return x>0

print(list(filter(positive, [1, -3, 2, 0, -5, 6]))) # 실행결과 [1, 2, 6]

lambda와 같이사용할 경우

list(filter(lambda x: x>0, [1,-3,2,0,-5,6]))
  • hex(x): 정수를 입력받아 16진수 문자열로 변환하여 반환
>>> hex(234)
'0xea'
>>> hex(3)
'0x3'
  • id(object): 객체를 입력받아 객체의 고유 주솟값을 반환하는 함수
>>> a=3
>>> id(3)
4378697552
>>> id(a)
4378697552
>>> b=a
>>> id(b)
4378697552
>>> id(4)
4378697584
  • input([prompt]): 사용자 입력을 받는 함수
>>>a=input()
hi
>>>a
'hi'
>>> b=input("Enter: ")
Enter: hi
>>> b
'hi'
  • int(x): 문자열 형태의 숫자나 소수점이 있는 숫자를 정수로 반환
>>> int('3')
3
>>> int(3.4)
3
  • int(x, radix): 진수로 표현된 문자열 x를 10진수로 변환하여 반환
>>> int('11', 2)
3
>>> int('1A', 16)
26
>>> int('16', 8)
14
  • isinstance(object, class): 객체와 클래스를 입력받아 객체가 클래스의 인스턴스인지를 판단하여 True 혹은 False를 반환
>>> class Person: pass
...
>>> a=Person()
>>> isinstance(a, Person)
True
>>> b=3
>>> isinstance(b, Person)
False
  • len(s): 입력값 s의 길이(요소의 전체 개수)를 반환
>>> len("python")
6
>>> len([1,2,3])
3
>>> len((1,'a'))
2
  • list(iterable): 반복 가능한 데이터를 입력받아 리스트로 만들어 반환
>>> list("python")
['p', 'y', 't', 'h', 'o', 'n']
>>> list((1,2,3))
[1, 2, 3]
>>> a=[1,2,3]
>>> b=list(a)
>>> b
[1, 2, 3]
  • map(f, iterable): 함수와 반복 가능한 데이터를 입력받아 데이터의 각 요소에 함수 f를 적용한 결과를 반환
def two_times(x):
    return x*2

list(map(two_times, [1,2,3,4])) #결과 [2, 4, 6, 8]

lambda와 같이사용할 경우

>>> list(map(lambda a: a*2, [1,2,3,4]))
[2, 4, 6, 8]
  • max(iterable)&min(iterable): 인수로 반복가능한 데이터를 입력받아 최댓값 및 최솟값을 반환
>>> max([1,2,3])
3
>>> max("python")
'y'
>>> min([1,2,3])
1
>>> min("python")
'h'
  • oct(x): 정수를 8진수 문자열로 바꾸어 반환
>>> oct(34)
'0o42'
>>> oct(12345)
'0o30071'
  • open(filename, [mode]): 파일 이름과 읽기 방법을 입력받아 파일 객체를 반환
mode설명
w쓰기 모드
r읽기 모드
a추가 모드
b바이너리 모드
# 예시
f=open("test.txt", 'w')
  • ord(c): 문자의 유니코드 숫자값을 반환
>>> ord('a')
97
>>> ord('가')
44032
  • pow(x,y): x를 y제곱한 결과값을 반환
>>> pow(2,4)
16
>>> pow(3,3)
27
  • range([start,]stop[,step]) 입력받은 숫자에 해당하는 범위 값을 반복 가능한 객체로 반환. 주로 for문과 함께 사용
>>> list(range(5))
[0, 1, 2, 3, 4]
>>> list(range(5,10))
[5, 6, 7, 8, 9]
>>> list(range(1,10,2))
[1, 3, 5, 7, 9]
>>> list(range(0,-10,-1))
[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
  • round(num[,ndigits]): 숫자를 입력받아 반올림해 반환
>>> round(4.6)
5
>>> round(4.2)
4
>>> round(5.678,2)
5.68
  • sorted(iterable): 입력 데이터를 정렬한 후 그 결과를 리스트로 반환
>>> sorted([3,1,2])
[1, 2, 3]
>>> sorted(['a','c','b'])
['a', 'b', 'c']
>>> sorted("zero")
['e', 'o', 'r', 'z']
>>> sorted((3,2,1))
[1, 2, 3]
  • str(object): 문자열 형태로 객체를 변환하여 반환
>>> str(3)
'3'
>>> str('hi')
'hi'
  • sum(iterable): 입력 데이터의 합을 반환
>>> sum([1,2,3])
6
>>> sum((4,5,6))
15
  • tuple(iterable): 반복 가능한 데이터를 튜플로 바꾸어 반환
>>> tuple("abc")
('a', 'b', 'c')
>>> tuple([1,2,3])
(1, 2, 3)
>>> tuple((1,2,3))
(1, 2, 3)
  • type(object): 입력값의 자료형을 알려주는 함수
>>> type("abc")
<class 'str'>
>>> type([])
<class 'list'>
>>> type(open("test", 'w'))
<class '_io.TextIOWrapper'>
  • zip(*iterable): 동일한 개수로 이루어진 데이터들을 묶어서 반환
>>> list(zip([1,2,3],[4,5,6]))
[(1, 4), (2, 5), (3, 6)]
>>> list(zip([1,2,3],[4,5,6],[7,8,9]))
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
>>> list(zip("abc", "def"))
[('a', 'd'), ('b', 'e'), ('c', 'f')]

내부함수와 외부함수

Python은 함수 안에 함수를 정의할수 있음. 함수 안쪽의 함수를 내부 함수, 함수 바깥쪽의 함수를 외부 함수라 함.

def outer():
    def inner():
        print("inner")
    return inner

f=outer()
f()

LEGB 규칙

변수의미
LLocal의 약자로 함수 안을 의미
EEnclosed function locals의 약자로 내부함수에서 자신의 외부 함수의 범위를 의미
GGlobal의 약자로 함수 바깥 즉, 모듈 범위
BBuilt-in의 약자로 open, range와 같은 파이썬 내장함수들을 의미
a=10

def test():
    a=20
    print(a)

test() # 20을 출력
a=10

def test():
    print(a)
    
test() # 10을 출력
  • 변수 바인딩
a=10

def test():
    a=20
    print(a)
    
test()
print(a)
20
10
a=10

def test():
    global a
    a=20
    
test()
print(a)
20

Enclosed Function Locals

def outer():
    inner=3
    return inner

f=outer()
def outer():
    num=3 # num이 Enclosed function locals 영역의 변수
    def inner():
        print(num)
    return inner

f=outer()
f()
print(f.__closure__[0].cell_contents)
print(type(f.__closure__)) # tuple
print(type(f.__closure__[0])) # cell
print(dir(f.__closure__[0]))

Closure

def outer(num):
    def inner():
        print(num)
    return inner
f1=outer(3)
f2=outer(4)
f1()
f2()
  • class로 구현
class Outer:
    def __init__(self, num):
        self.num=num
    def __call__(self):
        print(self.num)
        
f1=Outer(3)
f1()

Class

Class는 데이터와 이를 처리하는 메서드(함수)로 구성됨. 파이썬에서는 class라는 키워드를 사용하면 사용자가 새로운 타입을 생성할 수 있음.

class Person:
    pass

p=Person()
class Person:
    pass

p=Person()
p.data=3
  • 클래스 공간에 데이터 저장
class Person:
    data=4

p=Person()
  • 객체는 서로 다른 공간에 있으며 각 객체에 대한 데이터는 클래스에 있을 필요가 없음
class Person:
    pass

p1=Person()
p2=Person()
p1.balance=1000
p2.balance=100

Initialization

일반적으로 함수는 사용자가 함수이름()과 같은 형태로 호출해야 코드가 수행되지만 클래스는 클래스 내의 특별한 이름(__init__)을 갖기만 하면 객체가 생성될때 자동으로 호출되는 함수가 있다. 이를 생성자(Initialization)이라고 한다.

class Person:
    def __init__(self):
        print("태어남..")
        
p=Person()

인스턴스 개수 세기

class MyClass:
    count=0
    
    def __init__(self):
        MyClass.count+=1
        
    def get_count(self):
        return MyClass.count
    
a=MyClass()
b=MyClass()
c=MyClass()

print(a.get_count())

매직 메서드(Magic Method)

클래서 안에 정의된 함수를 method라고 부르며, 메소드 중에서 양옆에 __가 있는 메소드가 있는데, 이를 매직 메소드(Magic Method)또는 특별 메소드(Special Method)라고 부름 파이썬의 매직 메소드는 특별한 기능을 제공함

  • __call__
class MyFunc:
    def __call__(self, *args, **kwargs):
        print("호출됨")
        
f=MyFunc()
f()
  • __getattribute__
class Stock:
    def __getattribute__(self, item):
        print(item, "객체에 접근하셨습니다.")
        
s=Stock()
s.data
  • hasattr(object, name)
class Car:
    def __init__(self):
        self.wheels=4
    def drive(self):
        print("drive")
        
mycar=Car()

# 둘다 True
hasattr(mycar, "wheels")
hasattr(mycar, "drive")
  • getattr(object, name[,default])
mycar=Car()

getattr(mycar, "wheels")

method=getattr(mycar, "drive")
method()

추상클래스(Abstract Class)

추상 클래스란 메소드의 이름만 존재하는 클래스로, 부모 클래스에 메소드만을 정의하고 이를 상속 받은 클래스가 해당 매소드를 반드시 구현하도록 강제하기 위해 사용된다.

from abc import *

class Car(metaclass=ABCMeta):
    @abstractmethod
    def drive(self):
        pass
    
class K5(Car):
    def drive(self):
        print("k5 drive")
        
k5=K5()
k5.drive()

클래스의 속성

클래스의 상태를 나타내며 클래스 내에서 정의된 변수로, 객체별로 고유하거나 클래스 자체에서 공유할 수도 있음.

class MyClass:
    
    a="hi" # 클래스 속성
    
    def __init__(self, b):
        self.b=b # 인스턴스 속성
        
    def show(self):
        print(MyClass.a)
        print(self.b)
        
a=MyClass("world")
a
>>> a.a
'hi'
>>> a.b
'world'

클래스의 Method

클래스나 객체가 수행할 수 있는 기능을 정의. 메서드는 함수와 유사하지만, 클래스 내부에서 정의되고, 객체를 통해 호출.

  • 인스턴스 메소드: self를 첫번째 매개변수로 사용하며, 인스턴스 속성에 접근
  • 클래스 메소드: @classmethod 데코레이터를 사용하며 cls를 통해 클래스 속성에 접근
  • 정적 메소드: @staticmethod 데코레이터를 사용하며, 속성에 직접 접근하지 않음.
class MyClass:
    a=0 # 클래스 속성
    def __init__(self, name): # 매직 메소드
        self.name=name
    
    def instance(self): # 인스턴스 메소드
        print(f"Hello, {self.name}")
        
    @classmethod
    def clsmethod(cls): # 클래스 메소드
        cls.a+=1
        print(cls.a)
        
    @staticmethod
    def static_method(): # 정적 메소드
        print("static method")
        
>>> a=MyClass('world')
>>> a.instance()
Hello, world
>>> a.clsmethod()
1
>>> a.static_method()
static method

클래스 상속

기존 클래스를 확장하여 새로운 클래스를 정의할 수 있으며. 이를 통해 코드 재사용성을 높이고, 기존 클래스의 기능을 유지하면서 추가적이거나 수정된 기능을 쉽게 구현 가능

class ParentClass:
    def __init__(self, value):
        self.value = value

    def show_value(self):
        print(f"Value: {self.value}")


# ParentClass를 상속받는 ChildClass
class ChildClass(ParentClass):
    def __init__(self, value, extra_value):
        super().__init__(value)  # 부모 클래스의 생성자 호출
        self.extra_value = extra_value

    def show_extra_value(self):
        print(f"Extra Value: {self.extra_value}")


# 사용 예시
parent = ParentClass(10)
parent.show_value()  # Output: Value: 10

child = ChildClass(20, 30)
child.show_value()  # Output: Value: 20
child.show_extra_value()  # Output: Extra Value: 30
  • super(): 자식 클래스에서 부모 클래스의 메소드나 속성에 접근할때 사용 되며 생성자 호출시 부모 클래스 초기화를 명시적으로 호출해야 할때 유용
class Parent:
    def __init__(self, name):
        self.name = name


class Child(Parent):
    def __init__(self, name, age):
        super().__init__(name)  # 부모 클래스의 __init__ 호출
        self.age = age
  • Method Overriding: 부모 클래스의 메서드를 자식 클래스에서 동일한 이름으로 재정의 할수 있으며 오버라이딩된 메서드에서 부모 클래스의 메서드를 호출하려면 super()를 사용.
class Parent:
    def greet(self):
        print("Hello from Parent!")


class Child(Parent):
    def greet(self):
        super().greet()  # 부모 클래스의 greet 호출
        print("Hello from Child!")


obj = Child()
obj.greet()
# Output:
# Hello from Parent!
# Hello from Child!
  • 다중 상속: 파이썬은 다중 상속을 지원함. 단, 다이아몬드 상속 문제(여러 부모 클래스에서 중복된 메서드가 있을 경우 우선순위 결정) 등을 처리하기 위해 MRO(Method Resolution Order) 를 사용.
class A:
    def method(self):
        print("Method in A")


class B(A):
    def method(self):
        print("Method in B")


class C(A):
    def method(self):
        print("Method in C")


class D(B, C):  # B와 C를 동시에 상속
    pass


obj = D()
obj.method()  # Output: Method in B (MRO 순서에 따라 결정)
profile
인공지능 관련 분야에 관심있습니다.

0개의 댓글