본문 바로가기

Python study

property

데이터 랭글링(Data Wrangling)

데이터 랭글링(Data Wrangling)이란, 원시 데이터를 분석에 적합한 형태로 변환하고 정리하는 과정을 말한다. 데이터 랭글링은 데이터 전처리(data preprocessing)의 중요한 부분으로, 데이터 분석가와 과학자들이 데이터 분석이나 모델링을 수행하기 전에 반드시 거쳐야 하는 단계이다.

데이터 랭글링의 주요 단계

  1. 데이터 수집:
    • 다양한 소스(파일, 데이터베이스, 웹, API 등)에서 데이터를 수집한다.
  2. 데이터 구조화:
    • 비정형 데이터를 정형 데이터로 변환하여 테이블 형식으로 만든다.
    • 데이터 프레임(pandas DataFrame) 같은 구조로 데이터를 정리한다.
  3. 데이터 정리 및 클렌징:
    • 누락된 값(missing values) 처리: 결측값을 제거하거나 대체한다.
    • 중복 데이터 제거: 중복된 행이나 열을 찾아 제거한다.
    • 오류 데이터 수정: 잘못된 형식이나 범위를 벗어난 데이터를 수정한다.
  4. 데이터 변환:
    • 데이터 타입 변환: 문자열, 숫자, 날짜 등 데이터 타입을 변환한다.
    • 새로운 변수 생성: 기존 데이터를 바탕으로 새로운 변수를 만든다.
    • 데이터 정규화(normalization) 및 표준화(standardization): 데이터 스케일을 맞춘다.
  5. 데이터 통합:
    • 여러 소스에서 온 데이터를 병합(merge)하거나 결합(concatenate)하여 하나의 데이터 세트로 만든다.
  6. 데이터 필터링 및 선택:
    • 분석에 필요한 데이터만 선택하고, 불필요한 데이터는 제거한다.
  7. 데이터 요약 및 집계:
    • 데이터를 그룹화하여 요약 통계를 계산하거나 집계한다.
import pandas as pd
import numpy as np

# 데이터 수집
data = {
    'name': ['Alice', 'Bob', 'Charlie', None],
    'age': [25, 30, 35, np.nan],
    'email': ['alice@example.com', 'bob@example.com', 'charlie@example.com', None]
}

df = pd.DataFrame(data)

# 데이터 정리 및 클렌징
df.dropna(subset=['name', 'email'], inplace=True)  # name과 email에 결측값이 있는 행 제거
df['age'].fillna(df['age'].mean(), inplace=True)  # age의 결측값을 평균으로 대체

# 데이터 변환
df['age'] = df['age'].astype(int)  # age를 정수형으로 변환

# 데이터 필터링 및 선택
filtered_df = df[df['age'] > 30]  # age가 30보다 큰 데이터만 선택

# 데이터 요약 및 집계
summary = df.groupby('age').size()  # age별로 그룹화하여 개수 세기

print("Filtered DataFrame:")
print(filtered_df)
print("\\nSummary by Age:")
print(summary)

'''
Filtered DataFrame:
      name  age              email
2  Charlie   35  charlie@example.com

Summary by Age:
age
25    1
30    1
35    1
dtype: int64
'''

이 예제에서는 데이터 프레임을 생성하고, 결측값을 처리하며, 데이터 타입을 변환하고, 특정 조건에 맞는 데이터를 필터링하며, 데이터를 그룹화하여 요약 통계를 계산하는 과정을 보여준다. 이처럼 데이터 랭글링은 데이터 분석의 필수적인 단계로, 데이터의 품질을 높이고 분석을 더 정확하게 할 수 있게 도와준다.

 

동적 속성을 이용한 데이터 랭글링

동적 속성을 이용한 데이터 랭글링(Dynamic Attributes for Data Wrangling)에 대해 설명하겠다. 동적 속성은 객체의 속성을 런타임에 동적으로 정의하거나 수정하는 기법으로, 파이썬의 유연성을 극대화하여 다양한 상황에서 유용하게 사용할 수 있다. 특히 데이터 랭글링 과정에서 데이터 구조가 정적이지 않거나, 다양한 형태의 데이터를 다룰 때 유용하다.

기본 개념

  1. 기본 속성 정의:
    • 클래스 내에서 init 메서드를 사용하여 기본 속성을 정의한다.
    class DataObject:
        def __init__(self, name, value):
            self.name = name
            self.value = value
    
  2. 동적 속성 추가:
    • setattr 함수를 사용하여 객체에 동적으로 속성을 추가한다.
    data = DataObject("sample", 10)
    setattr(data, 'new_attr', 20)
    print(data.new_attr)  # 출력: 20
    
  3. 동적 속성 접근:
    • getattr 함수를 사용하여 동적으로 추가된 속성에 접근할 수 있다.
    value = getattr(data, 'new_attr')
    print(value)  # 출력: 20
    

데이터 랭글링에서의 활용

  1. 데이터 변환 및 처리:
    • 다양한 형식의 데이터가 포함된 객체에 동적으로 속성을 추가하여 데이터 변환 및 처리에 유용하게 사용할 수 있다.
    class FlexibleData:
        def __init__(self, data):
            for key, value in data.items():
                setattr(self, key, value)
    
    data = {
        'name': 'Alice',
        'age': 30,
        'country': 'Wonderland'
    }
    
    flexible_data = FlexibleData(data)
    print(flexible_data.name)  # 출력: Alice
    print(flexible_data.age)   # 출력: 30
    print(flexible_data.country)  # 출력: Wonderland
    
  2. 데이터 프레임과의 연동:
    • pandas 데이터 프레임과 동적 속성을 활용하여 각 행을 객체로 변환하고 처리할 수 있다.
    import pandas as pd
    
    class DataFrameRow:
        def __init__(self, **kwargs):
            for key, value in kwargs.items():
                setattr(self, key, value)
    
    df = pd.DataFrame({
        'name': ['Alice', 'Bob'],
        'age': [30, 25]
    })
    
    objects = [DataFrameRow(**row) for index, row in df.iterrows()]
    
    for obj in objects:
        print(obj.name, obj.age)
    # 출력:
    # Alice 30
    # Bob 25
    
  3. 데이터 클렌징:
    • 동적 속성을 활용하여 데이터 클렌징 과정에서 필요에 따라 속성을 추가하거나 제거할 수 있다.
    class DataCleaner:
        def __init__(self, **kwargs):
            for key, value in kwargs.items():
                setattr(self, key, value)
    
        def clean(self):
            for attr in list(self.__dict__.keys()):
                if getattr(self, attr) is None:
                    delattr(self, attr)
    
    raw_data = {
        'name': 'Charlie',
        'age': None,
        'email': 'charlie@example.com'
    }
    
    cleaner = DataCleaner(**raw_data)
    cleaner.clean()
    print(cleaner.__dict__)  # 출력: {'name': 'Charlie', 'email': 'charlie@example.com'}
    

이와 같이 동적 속성을 사용하면 데이터의 형태와 구조가 변하는 상황에서도 유연하게 대처할 수 있다. 이는 데이터 랭글링 과정에서 복잡한 데이터를 효율적으로 처리하고 변환하는 데 매우 유용하다.

 

동적 속성을 이용해서 JSON과 유사한 데이터 둘러보기

동적 속성을 이용하여 JSON과 유사한 데이터를 다루는 방법은 객체 지향 프로그래밍의 유연성을 활용하여 JSON 데이터를 더욱 직관적이고 간편하게 탐색할 수 있게 한다. 이를 통해 JSON 데이터를 객체처럼 다룰 수 있으며, 속성 접근 방식을 통해 데이터를 쉽게 탐색할 수 있다.

JSON 데이터 탐색을 위한 동적 속성 사용 예제

1. JSON 데이터 예제

json_data = {
    "name": "Alice",
    "age": 30,
    "address": {
        "street": "123 Main St",
        "city": "Wonderland"
    },
    "hobbies": ["reading", "chess"]
}

2. JSON 데이터를 동적 속성으로 다루는 클래스 정의

  • 이 클래스는 JSON 데이터의 키를 속성으로 변환하여 동적으로 접근할 수 있게 한다.
class JSONObject:
    def __init__(self, data):
        for key, value in data.items():
            if isinstance(value, dict):
                value = JSONObject(value)  # 중첩된 dict를 JSONObject로 변환
            setattr(self, key, value)

    def __repr__(self):
        return f"JSONObject({self.__dict__})"

# JSON 데이터를 JSONObject로 변환
json_obj = JSONObject(json_data)

3. 동적 속성을 이용한 데이터 접근

  • JSON 데이터의 각 요소를 객체 속성처럼 접근할 수 있다.
print(json_obj.name)  # 출력: Alice
print(json_obj.age)   # 출력: 30
print(json_obj.address.street)  # 출력: 123 Main St
print(json_obj.hobbies)  # 출력: ['reading', 'chess']
  • 클래스 정의:
    • init 메서드에서 data의 키와 값을 반복하면서 속성을 동적으로 설정한다.
    • 만약 값이 dict 타입이라면 재귀적으로 JSONObject 인스턴스를 생성하여 중첩된 구조를 처리한다.
    • repr 메서드를 정의하여 객체를 출력할 때 가독성을 높인다.
  • 데이터 접근:
    • 변환된 json_obj 객체를 통해 JSON 데이터의 각 항목에 접근할 수 있다.
    • 중첩된 구조 역시 객체 속성처럼 접근이 가능하다.
class JSONObject:
    def __init__(self, data):
        for key, value in data.items():
            if isinstance(value, dict):
                value = JSONObject(value)  # 중첩된 dict를 JSONObject로 변환
            setattr(self, key, value)

    def __repr__(self):
        return f"JSONObject({self.__dict__})"

# JSON 데이터 예제
json_data = {
    "name": "Alice",
    "age": 30,
    "address": {
        "street": "123 Main St",
        "city": "Wonderland"
    },
    "hobbies": ["reading", "chess"]
}

# JSON 데이터를 JSONObject로 변환
json_obj = JSONObject(json_data)

# 동적 속성을 이용한 데이터 접근
print(json_obj.name)  # 출력: Alice
print(json_obj.age)   # 출력: 30
print(json_obj.address.street)  # 출력: 123 Main St
print(json_obj.hobbies)  # 출력: ['reading', 'chess']

이 방법을 사용하면 JSON 데이터를 객체 속성으로 직관적이고 쉽게 탐색할 수 있다. 특히 중첩된 구조를 다룰 때 매우 유용하며, 데이터를 더 자연스럽게 다룰 수 있게 도와준다.

잘못된 속성명 문제를 해결

위 예제에서 잘못된 속성명을 사용할 경우 에러를 방지하고, 유효하지 않은 속성 접근 시 사용자에게 유용한 피드백을 제공하는 방법을 추가할 수 있다. 이를 위해 getattr 메서드를 활용하여 잘못된 속성 접근을 처리하는 로직을 추가할 수 있다.

잘못된 속성명 문제 해결 예제

  1. 클래스 정의에 getattr 메서드 추가
    • getattr 메서드는 객체에 존재하지 않는 속성에 접근하려고 할 때 호출된다.
    • 이 메서드를 이용하여 잘못된 속성 접근 시 예외를 던지거나, 사용자에게 의미 있는 메시지를 반환할 수 있다.
class JSONObject:
    def __init__(self, data):
        for key, value in data.items():
            if isinstance(value, dict):
                value = JSONObject(value)  # 중첩된 dict를 JSONObject로 변환
            setattr(self, key, value)

    def __getattr__(self, name):
        raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{name}'")

    def __repr__(self):
        return f"JSONObject({self.__dict__})"

# JSON 데이터 예제
json_data = {
    "name": "Alice",
    "age": 30,
    "address": {
        "street": "123 Main St",
        "city": "Wonderland"
    },
    "hobbies": ["reading", "chess"]
}

# JSON 데이터를 JSONObject로 변환
json_obj = JSONObject(json_data)

# 동적 속성을 이용한 데이터 접근
print(json_obj.name)  # 출력: Alice
print(json_obj.age)   # 출력: 30
print(json_obj.address.street)  # 출력: 123 Main St
print(json_obj.hobbies)  # 출력: ['reading', 'chess']

# 잘못된 속성 접근 시 예외 발생
try:
    print(json_obj.invalid_attr)
except AttributeError as e:
    print(e)  # 출력: 'JSONObject' object has no attribute 'invalid_attr'
  • getattr 메서드:
    • 객체에 존재하지 않는 속성에 접근하려고 할 때 호출된다.
    • 해당 속성이 존재하지 않을 경우 AttributeError를 발생시키며, 사용자에게 유용한 메시지를 제공한다.
  • 잘못된 속성 접근 처리:
    • try...except 블록을 사용하여 잘못된 속성 접근 시 예외를 처리하고, 에러 메시지를 출력한다.

이렇게 getattr 메서드를 추가하면, 객체에 존재하지 않는 속성 접근 시 적절한 예외 처리가 가능해져 코드의 안정성과 디버깅 용이성이 향상된다.

 

new() 를 이용한 융통성 있는 객체 생성

new() 메서드는 Python의 객체 생성 과정에서 사용되는 특별한 메서드로, 인스턴스가 생성되기 전에 호출된다. 이는 주로 객체 생성의 제어를 위해 사용되며, 특히 불변 객체(immutable objects)나 싱글톤 패턴을 구현할 때 유용하다. new() 메서드를 활용하여 융통성 있는 객체 생성을 구현하는 방법에 대해 자세히 설명하겠다.

new() 메서드의 기본 개념

  • new() 메서드는 클래스의 새로운 인스턴스를 생성하는 책임을 진다.
  • 이는 정적 메서드(static method)처럼 동작하며, 첫 번째 인자로 클래스를 받는다.
  • new() 메서드는 반드시 새로운 인스턴스를 반환해야 한다.

new() 메서드 사용 예제

다음 예제에서는 new() 메서드를 사용하여 JSON 데이터를 동적으로 객체로 변환하는 과정을 설명하겠다.

class JSONObject:
    def __new__(cls, data):
        # 새 인스턴스 생성
        instance = super().__new__(cls)

        # 데이터를 객체 속성으로 설정
        for key, value in data.items():
            if isinstance(value, dict):
                value = JSONObject(value)  # 중첩된 dict를 JSONObject로 변환
            setattr(instance, key, value)

        return instance

    def __repr__(self):
        return f"JSONObject({self.__dict__})"

# JSON 데이터 예제
json_data = {
    "name": "Alice",
    "age": 30,
    "address": {
        "street": "123 Main St",
        "city": "Wonderland"
    },
    "hobbies": ["reading", "chess"]
}

# JSON 데이터를 JSONObject로 변환
json_obj = JSONObject(json_data)

# 동적 속성을 이용한 데이터 접근
print(json_obj.name)  # 출력: Alice
print(json_obj.age)   # 출력: 30
print(json_obj.address.street)  # 출력: 123 Main St
print(json_obj.hobbies)  # 출력: ['reading', 'chess']

# 잘못된 속성 접근 시 예외 발생
try:
    print(json_obj.invalid_attr)
except AttributeError as e:
    print(e)  # 출력: 'JSONObject' object has no attribute 'invalid_attr'
  1. new() 메서드 정의:
    • cls 인자로 클래스 자체를 받는다.
    • super().new(cls)를 호출하여 클래스의 새로운 인스턴스를 생성한다.
    • 생성된 인스턴스에 JSON 데이터를 속성으로 설정한다.
  2. 동적 속성 설정:
    • JSON 데이터의 각 키와 값을 반복하면서 객체의 속성으로 설정한다.
    • 값이 dict 타입인 경우 재귀적으로 JSONObject 인스턴스를 생성한다.
  3. 객체 반환:
    • new() 메서드는 새로 생성된 인스턴스를 반환한다.
  • new() 메서드를 사용하면 객체 생성 시 더 많은 제어권을 가질 수 있다.
  • 이 방법은 특히 객체의 초기 설정이나 특수한 객체 생성 로직이 필요한 경우에 유용하다.
  • 위 예제에서는 JSON 데이터를 동적 속성으로 설정하여, JSON 데이터 탐색을 더 직관적이고 간편하게 만들었다.

이 방법을 사용하면 JSON 데이터뿐만 아니라 다른 유사한 구조의 데이터를 다룰 때도 유연하고 효율적으로 처리할 수 있다.

 

shelve를 이용해서 OSCON 피드 구조 변경하기

shelve 모듈은 Python에서 간단한 영구적 저장소를 제공하는 모듈로, 객체를 파일에 저장하고, 저장된 객체를 쉽게 다시 불러올 수 있게 한다. 이는 파이썬의 내장 모듈로, pickle 모듈을 기반으로 하며, 딕셔너리와 유사한 인터페이스를 제공한다.

shelve 모듈 사용 개요

  • shelve 모듈은 키-값 쌍을 파일에 저장하고 불러올 수 있는 간단한 방법을 제공한다.
  • 데이터를 파일에 저장할 때 shelve.open을 사용하여 저장소를 열고, 딕셔너리와 유사한 방식으로 데이터를 저장하고 읽을 수 있다.
  • shelve는 내부적으로 데이터를 직렬화하여 파일에 저장하기 때문에, 모든 pickle 가능한 객체를 저장할 수 있다.

shelve 사용 예제

import shelve

# 데이터 저장
with shelve.open('my_shelve.db') as db:
    db['name'] = 'Alice'
    db['age'] = 30
    db['hobbies'] = ['reading', 'chess']

# 데이터 불러오기
with shelve.open('my_shelve.db') as db:
    print(db['name'])  # 출력: Alice
    print(db['age'])   # 출력: 30
    print(db['hobbies'])  # 출력: ['reading', 'chess']

OSCON 피드 구조 변경

OSCON 피드 구조를 shelve 모듈을 사용하여 관리하는 방법을 살펴보겠다. 이를 위해 다음 단계들을 수행한다:

  1. OSCON 피드 데이터를 shelve에 저장하기:
    • 피드 데이터를 shelve를 사용하여 저장소에 저장한다.
  2. 피드 데이터 구조 변경:
    • 저장된 피드 데이터를 불러와서 구조를 변경하고, 다시 저장한다.

예제 데이터 및 구조 변경

가정:

  • OSCON 피드 데이터는 JSON 형식으로 되어 있으며, 각 피드는 title, description, tags 등을 포함한다.
  • 구조 변경은 예를 들어, tags를 별도의 리스트로 분리하거나, 새로운 필드를 추가하는 것을 포함한다.

1. 피드 데이터를 shelve에 저장하기

import shelve

# 예제 OSCON 피드 데이터
feeds = [
    {
        'id': 1,
        'title': 'Introduction to Python',
        'description': 'Learn the basics of Python.',
        'tags': ['python', 'beginner']
    },
    {
        'id': 2,
        'title': 'Advanced Python',
        'description': 'Deep dive into advanced Python topics.',
        'tags': ['python', 'advanced']
    }
]

# 피드 데이터를 shelve에 저장
with shelve.open('oscon_feeds.db') as db:
    for feed in feeds:
        db[str(feed['id'])] = feed

2. 피드 데이터 구조 변경

예를 들어, tags를 각 피드의 키로 분리하여 저장하거나 새로운 필드를 추가하는 경우이다.

import shelve

# 피드 데이터를 불러와서 구조 변경
with shelve.open('oscon_feeds.db', writeback=True) as db:
    for key in db:
        feed = db[key]
        # 예: 'tags'를 제거하고 별도의 리스트에 추가
        if 'tags' in feed:
            tags = feed.pop('tags')
            feed['tags_list'] = tags

        # 새로운 필드 추가
        feed['updated'] = True

        db[key] = feed  # 변경된 피드를 다시 저장

    # 변경된 데이터 확인
    for key in db:
        print(db[key])

전체 코드 통합

위의 각 단계를 통합하여 전체 코드를 구성하면 다음과 같다:

import shelve

# 1. 피드 데이터를 shelve에 저장하기
feeds = [
    {
        'id': 1,
        'title': 'Introduction to Python',
        'description': 'Learn the basics of Python.',
        'tags': ['python', 'beginner']
    },
    {
        'id': 2,
        'title': 'Advanced Python',
        'description': 'Deep dive into advanced Python topics.',
        'tags': ['python', 'advanced']
    }
]

with shelve.open('oscon_feeds.db') as db:
    for feed in feeds:
        db[str(feed['id'])] = feed

# 2. 피드 데이터 구조 변경하기
with shelve.open('oscon_feeds.db', writeback=True) as db:
    for key in db:
        feed = db[key]
        if 'tags' in feed:
            tags = feed.pop('tags')
            feed['tags_list'] = tags
        feed['updated'] = True
        db[key] = feed

    for key in db:
        print(db[key])
  • shelve 모듈을 사용하면 Python 객체를 쉽게 파일에 저장하고 불러올 수 있다.
  • OSCON 피드 데이터를 shelve에 저장한 후, 데이터 구조를 변경하고 다시 저장할 수 있다.
  • shelve를 사용하면 데이터베이스와 유사한 방식으로 데이터를 관리할 수 있어, 복잡한 데이터 구조도 손쉽게 다룰 수 있다.

 

프로퍼티를 이용해서 연결된 레코드 읽기

프로퍼티를 이용하여 연결된 레코드를 읽는 방법에 대해 설명하겠다. 이 접근 방식은 객체 지향 프로그래밍에서 데이터베이스나 다른 데이터 소스의 레코드들을 객체로 매핑하고, 객체의 프로퍼티를 통해 관련된 데이터를 동적으로 읽어오는 데 유용하다.

예제 시나리오

  • 우리는 두 개의 테이블 또는 데이터 구조를 가지고 있다고 가정한다: Users와 Orders.
  • 각 User는 여러 Orders를 가질 수 있다.
  • 사용자 객체를 생성하고, 프로퍼티를 사용하여 해당 사용자의 주문을 동적으로 읽어오는 예제를 만들어 보겠다.

단계별 구현

  1. 기본 데이터 구조 정의
  2. 프로퍼티를 사용하여 연결된 레코드 접근
  3. 예제 코드 실행

1. 기본 데이터 구조 정의

먼저 Users와 Orders 데이터 구조를 정의한다. 여기서는 간단하게 리스트를 사용하여 데이터를 저장한다.

# 예제 데이터
users_data = [
    {'id': 1, 'name': 'Alice'},
    {'id': 2, 'name': 'Bob'}
]

orders_data = [
    {'id': 1, 'user_id': 1, 'product': 'Laptop'},
    {'id': 2, 'user_id': 1, 'product': 'Mouse'},
    {'id': 3, 'user_id': 2, 'product': 'Keyboard'}
]

2. 사용자와 주문 클래스 정의

User 클래스에서 프로퍼티를 사용하여 관련된 Order 레코드를 동적으로 읽어오도록 한다.

class Order:
    def __init__(self, order_id, user_id, product):
        self.id = order_id
        self.user_id = user_id
        self.product = product

    def __repr__(self):
        return f"Order(id={self.id}, user_id={self.user_id}, product='{self.product}')"

class User:
    def __init__(self, user_id, name):
        self.id = user_id
        self.name = name

    @property
    def orders(self):
        # 'self.id'를 사용하여 관련된 주문을 필터링
        return [order for order in orders if order.user_id == self.id]

    def __repr__(self):
        return f"User(id={self.id}, name='{self.name}')"

# Order 객체 생성
orders = [Order(**order) for order in orders_data]

# User 객체 생성
users = [User(**user) for user in users_data]

3. 예제 코드 실행

이제 User 객체를 통해 Order 데이터를 동적으로 접근할 수 있다.

# 각 사용자의 주문 출력
for user in users:
    print(f"User: {user.name}")
    print("Orders:")
    for order in user.orders:
        print(f"  - {order}")

전체 코드

전체 코드를 하나로 통합하면 다음과 같다:

# 예제 데이터
users_data = [
    {'user_id': 1, 'name': 'Alice'},
    {'user_id': 2, 'name': 'Bob'}
]

orders_data = [
    {'order_id': 1, 'user_id': 1, 'product': 'Laptop'},
    {'order_id': 2, 'user_id': 1, 'product': 'Mouse'},
    {'order_id': 3, 'user_id': 2, 'product': 'Keyboard'}
]


class Order:
    def __init__(self, order_id, user_id, product):
        self.id = order_id
        self.user_id = user_id
        self.product = product

    def __repr__(self):
        return f"Order(id={self.id}, user_id={self.user_id}, product='{self.product}')"


class User:
    def __init__(self, user_id, name):
        self.id = user_id
        self.name = name

    @property
    def orders(self):
        # 'self.id'를 사용하여 관련된 주문을 필터링
        return [order for order in orders if order.user_id == self.id]

    def __repr__(self):
        return f"User(id={self.id}, name='{self.name}')"


# Order 객체 생성
orders = [Order(**order) for order in orders_data]

# User 객체 생성
users = [User(**user) for user in users_data]

# 각 사용자의 주문 출력
for user in users:
    print(f"User: {user.name}")
    print("Orders:")
    for order in user.orders:
        print(f"  - {order}")

'''
User: Alice
Orders:
  - Order(id=1, user_id=1, product='Laptop')
  - Order(id=2, user_id=1, product='Mouse')
User: Bob
Orders:
  - Order(id=3, user_id=2, product='Keyboard')
'''
  1. 데이터 초기화:
    • users_data와 orders_data는 사용자와 주문 데이터를 저장하는 리스트이다.
  2. 클래스 정의:
    • Order 클래스는 각 주문의 정보를 저장한다.
    • User 클래스는 사용자 정보를 저장하며, orders 프로퍼티를 통해 사용자의 주문을 동적으로 가져온다.
  3. 프로퍼티 사용:
    • User 클래스의 orders 프로퍼티는 사용자의 ID(self.id)를 사용하여 해당 사용자의 주문을 필터링한다.
  4. 데이터 접근:
    • users 리스트의 각 사용자에 대해 orders 프로퍼티를 사용하여 연결된 주문을 출력한다.

이 접근 방식은 객체 지향 프로그래밍의 장점을 활용하여, 데이터베이스의 레코드 간의 관계를 직관적이고 동적으로 처리할 수 있게 해준다. 프로퍼티를 사용하여 데이터 접근을 캡슐화하면 코드의 가독성과 유지보수성을 높일 수 있다.

 

속성을 검증하기 위해 프로퍼티 사용하기

속성을 검증하기 위해 프로퍼티를 사용하는 방법은 객체 지향 프로그래밍에서 속성 값을 설정할 때 유효성을 검사하고, 잘못된 값이 설정되지 않도록 하는 데 매우 유용하다. 이를 통해 클래스의 속성을 안전하게 관리하고, 객체 상태의 일관성을 유지할 수 있다.

기본 개념

property 데코레이터를 사용하면 속성 접근자(getter), 설정자(setter), 삭제자(deleter)를 정의할 수 있다. 이들 메서드를 사용하여 속성에 접근하거나 값을 설정할 때 추가적인 로직을 실행할 수 있다.

예제 시나리오

  • 우리는 Person 클래스를 정의하고, age 속성의 값을 설정할 때 검증을 수행해보겠다.
  • age 속성은 0보다 크거나 같고, 120보다 작거나 같은 값만 허용한다.

단계별 구현

  1. 기본 클래스 정의
  2. 프로퍼티를 사용한 속성 검증 추가
  3. 예제 코드 실행

1. 기본 클래스 정의

먼저 Person 클래스를 정의한다.

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

2. 프로퍼티를 사용한 속성 검증 추가

age 속성을 프로퍼티로 정의하여 설정할 때 검증을 추가한다.

class Person:
    def __init__(self, name, age):
        self.name = name
        self._age = None
        self.age = age  # 초기화 시 검증을 위해 setter를 사용

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
        if not (0 <= value <= 120):
            raise ValueError("Age must be between 0 and 120")
        self._age = value

3. 예제 코드 실행

이제 Person 객체를 생성하고, age 속성에 값을 설정할 때 검증이 잘 동작하는지 확인해보겠다.

# 올바른 나이 설정
try:
    person1 = Person("Alice", 30)
    print(f"{person1.name}의 나이: {person1.age}")  # 출력: Alice의 나이: 30
except ValueError as e:
    print(e)

# 잘못된 나이 설정
try:
    person2 = Person("Bob", 150)
except ValueError as e:
    print(e)  # 출력: Age must be between 0 and 120

# 나이 값 변경
try:
    person1.age = 25
    print(f"{person1.name}의 변경된 나이: {person1.age}")  # 출력: Alice의 변경된 나이: 25
    person1.age = -10  # 이 줄은 예외를 발생시킨다.
except ValueError as e:
    print(e)  # 출력: Age must be between 0 and 120

전체 코드 통합

전체 코드는 다음과 같다:

class Person:
    def __init__(self, name, age):
        self.name = name
        self._age = None
        self.age = age  # 초기화 시 검증을 위해 setter를 사용

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
        if not (0 <= value <= 120):
            raise ValueError("Age must be between 0 and 120")
        self._age = value


# 올바른 나이 설정
try:
    person1 = Person("Alice", 30)
    print(f"{person1.name}의 나이: {person1.age}")  # 출력: Alice의 나이: 30
except ValueError as e:
    print(e)

# 잘못된 나이 설정
try:
    person2 = Person("Bob", 150)
except ValueError as e:
    print(e)  # 출력: Age must be between 0 and 120

# 나이 값 변경
try:
    person1.age = 25
    print(f"{person1.name}의 변경된 나이: {person1.age}")  # 출력: Alice의 변경된 나이: 25
    person1.age = -10  # 이 줄은 예외를 발생시킨다.
except ValueError as e:
    print(e)  # 출력: Age must be between 0 and 120
  1. 클래스 초기화:
    • init 메서드에서 name과 _age를 초기화한다.
    • self.age = age를 사용하여 age의 값을 설정할 때 setter가 호출되어 검증이 수행된다.
  2. 프로퍼티 정의:
    • @property 데코레이터를 사용하여 age 속성의 getter를 정의한다.
    • @age.setter 데코레이터를 사용하여 age 속성의 setter를 정의한다.
    • setter 메서드에서 나이 값이 0에서 120 사이인지 검증하고, 그렇지 않으면 ValueError를 발생시킨다.
  3. 예제 실행:
    • 유효한 나이 값으로 Person 객체를 생성하고 값을 출력한다.
    • 잘못된 나이 값으로 Person 객체를 생성하려고 하면 예외를 발생시킨다.
    • 기존 객체의 나이 값을 변경할 때도 검증을 수행한다.

이와 같이 프로퍼티를 사용하면 속성에 접근할 때마다 검증 로직을 실행하여 잘못된 데이터가 설정되지 않도록 할 수 있다. 이를 통해 클래스의 속성을 안전하게 관리하고, 객체 상태의 일관성을 유지할 수 있다.

 

property()

property()는 파이썬에서 객체 지향 프로그래밍을 할 때 객체의 속성 접근을 캡슐화하기 위해 사용되는 내장 함수이다. property()를 사용하면 클래스의 속성에 접근할 때 특정 로직을 실행할 수 있다. 이를 통해 속성 값에 대한 유효성 검사를 하거나, 속성 값을 계산하여 반환할 수 있다.

기본 개념

property()는 다음과 같은 네 개의 인자를 가진다:

  • fget: 속성 값을 가져오는 함수 (getter)
  • fset: 속성 값을 설정하는 함수 (setter)
  • fdel: 속성을 삭제하는 함수 (deleter)
  • doc: 속성에 대한 설명 (optional)

property()를 사용하면 속성 접근, 설정, 삭제에 대한 사용자 정의 로직을 구현할 수 있다.

기본 사용법

class MyClass:
    def __init__(self, value):
        self._value = value

    def get_value(self):
        return self._value

    def set_value(self, value):
        if value < 0:
            raise ValueError("Value must be non-negative")
        self._value = value

    def del_value(self):
        del self._value

    value = property(get_value, set_value, del_value, "I'm the 'value' property.")

데코레이터를 사용한 프로퍼티 정의

Python에서는 데코레이터를 사용하여 더 간결하게 프로퍼티를 정의할 수 있다. 이는 코드의 가독성을 높이고, 유지보수를 쉽게 만든다.

class MyClass:
    def __init__(self, value):
        self._value = value

    @property
    def value(self):
        """I'm the 'value' property."""
        return self._value

    @value.setter
    def value(self, value):
        if value < 0:
            raise ValueError("Value must be non-negative")
        self._value = value

    @value.deleter
    def value(self):
        del self._value

객체 속성을 가리는 프로퍼티

객체 속성을 가리는 프로퍼티는 내부 속성(_value)을 외부에서 직접 접근하지 못하도록 숨기고, 프로퍼티를 통해서만 접근하게 만드는 기법이다. 이렇게 하면 속성에 대한 접근을 제어하고, 불필요한 외부 접근을 방지할 수 있다.

class MyClass:
    def __init__(self, value):
        self._value = value

    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, value):
        if value < 0:
            raise ValueError("Value must be non-negative")
        self._value = value

    @value.deleter
    def value(self):
        del self._value

# 예제 사용
obj = MyClass(10)
print(obj.value)  # 10

obj.value = 20
print(obj.value)  # 20

try:
    obj.value = -10
except ValueError as e:
    print(e)  # Value must be non-negative

del obj.value

실제 예제: 온도 변환 클래스

섭씨 온도를 화씨 온도로 변환하는 클래스를 만들어 보겠다. 여기서는 섭씨 온도를 설정하고, 화씨 온도를 읽어오는 프로퍼티를 사용한다.

class Temperature:
    def __init__(self, celsius):
        self._celsius = celsius

    @property
    def celsius(self):
        return self._celsius

    @celsius.setter
    def celsius(self, value):
        if value < -273.15:
            raise ValueError("Temperature below -273.15°C is not possible")
        self._celsius = value

    @property
    def fahrenheit(self):
        return (self._celsius * 9 / 5) + 32

# 예제 사용
temp = Temperature(25)
print(temp.celsius)      # 25
print(temp.fahrenheit)   # 77.0

temp.celsius = 30
print(temp.celsius)      # 30
print(temp.fahrenheit)   # 86.0

try:
    temp.celsius = -300
except ValueError as e:
    print(e)  # Temperature below -273.15°C is not possible
  • property()를 사용하면 객체의 속성 접근을 캡슐화할 수 있다.
  • getter, setter, deleter 메서드를 통해 속성의 읽기, 쓰기, 삭제 시 특정 로직을 실행할 수 있다.
  • 데코레이터(@property, @property.setter, @property.deleter)를 사용하면 더 간결하게 프로퍼티를 정의할 수 있다.
  • 객체 속성을 가리는 프로퍼티를 사용하면 속성 접근을 제어하고 객체 상태의 일관성을 유지할 수 있다.

이렇게 하면 속성 접근을 보다 안전하고 효율적으로 관리할 수 있으며, 코드의 가독성과 유지보수성을 높일 수 있다.

 

프로퍼티 팩토리 구현

프로퍼티 팩토리(Property Factory)는 여러 유사한 프로퍼티를 생성할 때 코드 중복을 줄이고, 공통된 로직을 캡슐화하기 위해 유용한 기법이다. 프로퍼티 팩토리를 사용하면 동적으로 프로퍼티를 생성할 수 있어 코드의 유연성과 재사용성을 높일 수 있다.

기본 개념

프로퍼티 팩토리는 함수나 클래스 메서드로 구현되며, 공통된 접근자(getter)와 설정자(setter) 로직을 정의한 후, 이를 사용하여 여러 프로퍼티를 생성한다. 이렇게 하면 프로퍼티 로직을 한 곳에서 관리할 수 있어 유지보수성을 크게 향상시킨다.

단계별 구현

  1. 기본 클래스 정의
  2. 프로퍼티 팩토리 함수 정의
  3. 프로퍼티 팩토리 사용

1. 기본 클래스 정의

먼저, 기본 클래스를 정의합니다. 이 클래스에는 여러 속성이 있으며, 각 속성은 공통된 검증 로직을 가진다.

class Product:
    def __init__(self, name, price, discount):
        self._name = name
        self._price = price
        self._discount = discount

2. 프로퍼티 팩토리 함수 정의

프로퍼티 팩토리 함수를 정의하여 getter와 setter 로직을 캡슐화한다.

def property_factory(private_name, validation_func=None):
    def getter(self):
        return getattr(self, private_name)

    def setter(self, value):
        if validation_func:
            validation_func(value)
        setattr(self, private_name, value)

    return property(getter, setter)

3. 프로퍼티 팩토리 사용

property_factory 함수를 사용하여 클래스의 프로퍼티를 생성한다.

class Product:
    def __init__(self, name, price, discount):
        self._name = name
        self._price = price
        self._discount = discount

    # 이름 프로퍼티 정의
    name = property_factory('_name')

    # 가격 프로퍼티 정의 (음수가 아닌지 검증)
    price = property_factory('_price', lambda v: v >= 0 or ValueError("Price must be non-negative"))

    # 할인율 프로퍼티 정의 (0과 1 사이의 값인지 검증)
    discount = property_factory('_discount', lambda v: 0 <= v <= 1 or ValueError("Discount must be between 0 and 1"))

# 예제 사용
product = Product("Laptop", 1000, 0.1)

print(product.name)     # Laptop
print(product.price)    # 1000
print(product.discount) # 0.1

product.price = 1200    # 정상 작동
print(product.price)    # 1200

try:
    product.price = -200  # 예외 발생
except ValueError as e:
    print(e)  # Price must be non-negative

try:
    product.discount = 1.5  # 예외 발생
except ValueError as e:
    print(e)  # Discount must be between 0 and 1

전체 코드 통합

전체 코드를 하나로 통합하면 다음과 같다:

def property_factory(private_name, validation_func=None):
    def getter(self):
        return getattr(self, private_name)

    def setter(self, value):
        if validation_func:
            if not validation_func(value):
                raise ValueError(f"Invalid value for {private_name}")
        setattr(self, private_name, value)

    return property(getter, setter)

class Product:
    def __init__(self, name, price, discount):
        self._name = name
        self._price = price
        self._discount = discount

    # 이름 프로퍼티 정의
    name = property_factory('_name')

    # 가격 프로퍼티 정의 (음수가 아닌지 검증)
    price = property_factory('_price', lambda v: v >= 0)

    # 할인율 프로퍼티 정의 (0과 1 사이의 값인지 검증)
    discount = property_factory('_discount', lambda v: 0 <= v <= 1)

# 예제 사용
product = Product("Laptop", 1000, 0.1)

print(product.name)     # Laptop
print(product.price)    # 1000
print(product.discount) # 0.1

product.price = 1200    # 정상 작동
print(product.price)    # 1200

try:
    product.price = -200  # 예외 발생
except ValueError as e:
    print(e)  # Price must be non-negative

try:
    product.discount = 1.5  # 예외 발생
except ValueError as e:
    print(e)  # Discount must be between 0 and 1
  1. 프로퍼티 팩토리 함수:
    • property_factory 함수는 getter와 setter를 정의하고, 주어진 검증 함수를 setter에서 사용한다.
    • validation_func는 값이 유효한지 검증하는 함수로, 기본적으로 None으로 설정된다.
    • getter는 private_name 속성의 값을 반환한다.
    • setter는 validation_func을 사용하여 값을 검증한 후, 유효한 경우 private_name 속성에 값을 설정한다.
  2. 클래스 정의:
    • Product 클래스의 각 속성은 property_factory를 사용하여 정의된다.
    • name 속성은 검증 없이 정의된다.
    • price 속성은 0보다 큰지 검증하는 함수를 사용하여 정의된다.
    • discount 속성은 0과 1 사이의 값인지 검증하는 함수를 사용하여 정의된다.
  3. 사용 예제:
    • Product 객체를 생성하고, 각 속성에 접근하거나 값을 설정할 때 프로퍼티 팩토리가 정의한 검증 로직이 동작하는 것을 확인할 수 있다.

이 접근 방식은 여러 프로퍼티가 동일한 검증 로직을 가질 때 코드 중복을 줄이고, 프로퍼티 정의를 보다 일관성 있게 유지할 수 있다. 또한, 필요에 따라 프로퍼티 정의를 쉽게 확장할 수 있어 코드의 유연성과 재사용성을 높일 수 있다.

 

속성 제거 처리

속성 제거 처리는 객체의 속성을 삭제할 때 필요한 로직을 정의하는 방법이다. 이를 통해 속성을 삭제할 때 추가적인 작업을 수행할 수 있다. Python에서는 @property 데코레이터와 함께 @property.deleter 데코레이터를 사용하여 속성을 제거할 때의 동작을 정의할 수 있다.

기본 개념

@property 데코레이터를 사용하여 getter, setter, deleter 메서드를 정의한다. deleter 메서드는 del 키워드를 사용하여 속성을 삭제할 때 호출된다. 이 메서드는 객체 상태를 관리하거나, 속성 삭제 시 필요한 추가 작업을 수행할 수 있다.

예제 시나리오

  • 우리는 Person 클래스를 정의하고, age 속성을 제거할 때 이를 처리하는 메서드를 구현해 보겠다.

단계별 구현

  1. 기본 클래스 정의
  2. 프로퍼티 정의 및 삭제자(deleter) 메서드 추가
  3. 예제 코드 실행

1. 기본 클래스 정의

먼저 Person 클래스를 정의한다.

class Person:
    def __init__(self, name, age):
        self._name = name
        self._age = age

2. 프로퍼티 정의 및 삭제자(deleter) 메서드 추가

age 속성을 프로퍼티로 정의하고, 삭제자(deleter) 메서드를 추가한다.

class Person:
    def __init__(self, name, age):
        self._name = name
        self._age = age

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
        if value < 0:
            raise ValueError("Age must be non-negative")
        self._age = value

    @age.deleter
    def age(self):
        print(f"Deleting age of {self._name}")
        del self._age

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        self._name = value

    @name.deleter
    def name(self):
        print(f"Deleting name of person with age {self._age}")
        del self._name

3. 예제 코드 실행

이제 Person 객체를 생성하고, age 속성을 삭제할 때의 동작을 확인해 보겠다.

# 객체 생성
person = Person("Alice", 30)

# 속성 접근 및 설정
print(person.age)  # 30
person.age = 25
print(person.age)  # 25

# 속성 삭제
del person.age
# 출력: Deleting age of Alice

try:
    print(person.age)
except AttributeError as e:
    print(e)  # 'Person' object has no attribute '_age'

# 이름 속성 삭제
del person.name
# 출력: Deleting name of person with age 25

전체 코드 통합

전체 코드를 하나로 통합하면 다음과 같다:

class Person:
    def __init__(self, name, age):
        self._name = name
        self._age = age

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
        if value < 0:
            raise ValueError("Age must be non-negative")
        self._age = value

    @age.deleter
    def age(self):
        print(f"Deleting age of {self._name}")
        del self._age

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        self._name = value

    @name.deleter
    def name(self):
        print(f"Deleting name of person with age {self._age}")
        del self._name

# 객체 생성
person = Person("Alice", 30)

# 속성 접근 및 설정
print(person.age)  # 30
person.age = 25
print(person.age)  # 25

# 속성 삭제
del person.age
# 출력: Deleting age of Alice

try:
    print(person.age)
except AttributeError as e:
    print(e)  # 'Person' object has no attribute '_age'

# 이름 속성 삭제
del person.name
# 출력: Deleting name of person with age 25
  1. 클래스 초기화:
    • init 메서드에서 name과 age를 초기화한다.
  2. 프로퍼티 정의:
    • @property 데코레이터를 사용하여 age와 name 속성의 getter를 정의한다.
    • @age.setter와 @name.setter 데코레이터를 사용하여 속성의 setter를 정의한다.
    • @age.deleter와 @name.deleter 데코레이터를 사용하여 속성의 deleter를 정의한다.
  3. 속성 삭제 처리:
    • del person.age를 사용하여 age 속성을 삭제할 때 @age.deleter 메서드가 호출된다. 이 메서드는 print 문을 통해 메시지를 출력하고, 실제로 _age 속성을 삭제한다.
    • del person.name를 사용하여 name 속성을 삭제할 때 @name.deleter 메서드가 호출된다. 이 메서드도 print 문을 통해 메시지를 출력하고, 실제로 _name 속성을 삭제한다.
  4. 예외 처리:
    • 속성이 삭제된 후 해당 속성에 접근하려고 하면 AttributeError가 발생하며, 이를 예외 처리로 확인할 수 있다.

이와 같이 속성 제거 처리기를 사용하면 객체의 속성을 삭제할 때 필요한 추가적인 작업을 수행할 수 있다. 이를 통해 객체 상태를 보다 정교하게 관리하고, 속성 삭제 시 필요한 로직을 캡슐화할 수 있다.

 

속성을 처리하는 핵심 속성 및 함수

Python에서 속성을 처리하는 데 사용되는 핵심 속성, 함수, 특별 메소드들에 대해 자세히 설명하겠다. 이들 도구들은 클래스와 객체의 속성 접근, 수정, 삭제 등을 세밀하게 제어할 수 있게 한다.

1. 특별 속성

특별 속성들은 클래스와 객체에 대한 메타 데이터를 제공하며, 속성 접근을 제어하는 데 사용된다.

  • dict: 객체의 속성들을 저장하는 사전이다. 이 사전을 통해 객체의 모든 속성과 그 값을 확인할 수 있다.
class MyClass:
    def __init__(self, value):
        self.value = value

obj = MyClass(10)
print(obj.__dict__)  # {'value': 10}
  • slots: 객체의 속성들을 고정하여 메모리 사용을 최적화한다. __dict__를 사용하지 않고 고정된 속성만 허용한다.
class MyClass:
    __slots__ = ['value']

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

obj = MyClass(10)
print(obj.value)  # 10
# print(obj.__dict__)  # AttributeError: 'MyClass' object has no attribute '__dict__'

2. 내장 함수

  • getattr(): 객체에서 속성을 동적으로 가져온다. 속성이 없으면 AttributeError를 발생시키거나 기본값을 반환한다.
class MyClass:
    def __init__(self, value):
        self.value = value

obj = MyClass(10)
print(getattr(obj, 'value'))  # 10
print(getattr(obj, 'nonexistent', 'default'))  # default
  • setattr(): 객체에 속성을 동적으로 설정한다.
class MyClass:
    pass

obj = MyClass()
setattr(obj, 'value', 10)
print(obj.value)  # 10
  • delattr(): 객체의 속성을 동적으로 삭제한다.
class MyClass:
    def __init__(self, value):
        self.value = value

obj = MyClass(10)
delattr(obj, 'value')
# print(obj.value)  # AttributeError: 'MyClass' object has no attribute 'value'
  • hasattr(): 객체에 속성이 존재하는지 확인한다.
class MyClass:
    def __init__(self, value):
        self.value = value

obj = MyClass(10)
print(hasattr(obj, 'value'))  # True
print(hasattr(obj, 'nonexistent'))  # False

3. 특별 메소드

특별 메소드들은 객체의 속성 접근, 설정, 삭제 등을 커스터마이징할 수 있게 해준다.

  • getattr(): 객체에 없는 속성에 접근할 때 호출된다.
class MyClass:
    def __getattr__(self, name):
        return f"Attribute {name} not found"

obj = MyClass()
print(obj.nonexistent)  # Attribute nonexistent not found
  • setattr(): 객체의 속성을 설정할 때 호출된다. 모든 속성 설정에 대한 제어를 제공한다.
class MyClass:
    def __setattr__(self, name, value):
        print(f"Setting {name} to {value}")
        super().__setattr__(name, value)

obj = MyClass()
obj.value = 10  # Setting value to 10
print(obj.value)  # 10
  • delattr(): 객체의 속성을 삭제할 때 호출된다.
class MyClass:
    def __init__(self, value):
        self.value = value

    def __delattr__(self, name):
        print(f"Deleting {name}")
        super().__delattr__(name)

obj = MyClass(10)
del obj.value  # Deleting value
# print(obj.value)  # AttributeError: 'MyClass' object has no attribute 'value'
  • dir(): dir() 함수가 호출될 때 반환할 속성 목록을 정의한다.
class MyClass:
    def __dir__(self):
        return ['custom_attr', 'another_attr']

obj = MyClass()
print(dir(obj))  # ['another_attr', 'custom_attr']

예제: 속성 접근을 커스터마이징한 클래스

아래 예제는 위의 특별 메소드들을 활용하여 속성 접근을 커스터마이징한 클래스이다.

class CustomClass:
    def __init__(self, value):
        self._value = value

    def __getattr__(self, name):
        if name == 'value':
            return self._value
        raise AttributeError(f"'CustomClass' object has no attribute '{name}'")

    def __setattr__(self, name, value):
        if name == 'value':
            if value < 0:
                raise ValueError("Value must be non-negative")
            self._value = value
        else:
            super().__setattr__(name, value)

    def __delattr__(self, name):
        if name == 'value':
            print(f"Deleting {name}")
            super().__delattr__(f'_{name}')
        else:
            super().__delattr__(name)

    def __dir__(self):
        return ['value', '_value']

# 예제 사용
obj = CustomClass(10)
print(obj.value)  # 10

obj.value = 20
print(obj.value)  # 20

try:
    obj.value = -10
except ValueError as e:
    print(e)  # Value must be non-negative

del obj.value  # Deleting value
  • 특별 속성: dict, slots 등을 통해 객체의 메타 데이터를 관리하고, 속성 접근을 제어할 수 있다.
  • 내장 함수: getattr(), setattr(), delattr(), hasattr()를 사용하여 객체의 속성을 동적으로 관리할 수 있다.
  • 특별 메소드: getattr(), setattr(), delattr(), dir()을 사용하여 속성 접근, 설정, 삭제, 나열 등의 동작을 커스터마이징할 수 있다.

이러한 도구들을 사용하면 Python 객체의 속성을 세밀하게 제어하고, 필요한 경우 동적으로 속성을 관리할 수 있어 유연한 프로그래밍이 가능하다.

 

모든 코드는 github에 저장되어 있습니다.

https://github.com/SeongUk18/python

 

728x90

'Python study' 카테고리의 다른 글

클래스 메타프로그래밍  (0) 2024.06.07
속성 디스크립터 (Descriptor)  (1) 2024.06.07
asynico를 이용한 동시성  (1) 2024.06.06
Future를 이용한 동시성  (1) 2024.06.04
코루틴 (coroutine)  (1) 2024.06.04