본문 바로가기
대학원 공부/programming language

Python : @property, method_name.setter 관련 오류, object is not callable 해결 방법

by 월곡동로봇팔 2020. 7. 1.

처음 오류 났을 때의 코드

##################
#    Model.py    #
##################

class BO_3D(object):	
    def __init__(self, x1_range, x2_range, new_property):
        self.__x1_range = x1_range
        self.__x2_range = x2_range
        self.__new_property = new_property

        temp_object = BayesianOptimization(f=None, pbounds={'x1': self.__x1_range, 'x2' : self.__x2_range}, verbose=2, random_state=1,)
        
        self.__optimizer = temp_object
        
        self.__utility = UtilityFunction(kind="ucb", kappa=2, xi=0.0)

        print("Our property what we want is "+str(self.__new_property))

        next_point_to_probe = self.__optimizer.suggest(self.__utility)
        print("Next point to probe is:", next_point_to_probe)
        
        target = -abs(float(input('파장을 입력하세요 : '))-self.__new_property)
        
        self.__optimizer.register(params=next_point_to_probe, target=target)
    
    @property
    def get_x1_range(self):
        """
            Purpose : --> return int(__x1_range)
        """
        return self.__x1_range

    @get_x1_range.setter
    def get_x1_range(self, x1_range):
        """
            Purpose : --> get __x1_range to new __x1_range
        """
        self.__x1_range = x1_range
        
##################
#     Main.py    #
################### 

main_new_property = bo_object.get_new_property()
main_optimizer = bo_object.get_optimizer()
main_utility = bo_object.get_utility()

위의 코드를 보면, class를 구성하고, x1_range를 private한 변수로 감쌌다. 

 

private한 변수로 감싸기위해서는 __x1_range라고 앞에 __ 언더바 두 개를 붙이면 된다.


이 상황에서 get, set 기능을 하는 method들을 호출해서 값을 집어넣으려하니

 

Traceback (most recent call last):
  File "./Algorithm/main_BO.py", line 15, in <module>
    print(bo_object.x1_range())
TypeError: 'tuple' object is not callable

이런식으로 자꾸 callable하지 않다고 나온다...

 

 

이거 때문에 2시간은 버린 듯...


해결방법

##################
#    Model.py    #
##################

class BO_3D(object):	
    def __init__(self, x1_range, x2_range, new_property):
        self.__x1_range = x1_range
        self.__x2_range = x2_range
        self.__new_property = new_property

        temp_object = BayesianOptimization(f=None, pbounds={'x1': self.__x1_range, 'x2' : self.__x2_range}, verbose=2, random_state=1,)
        
        self.__optimizer = temp_object
        
        self.__utility = UtilityFunction(kind="ucb", kappa=2, xi=0.0)

        print("Our property what we want is "+str(self.__new_property))

        next_point_to_probe = self.__optimizer.suggest(self.__utility)
        print("Next point to probe is:", next_point_to_probe)
        
        target = -abs(float(input('파장을 입력하세요 : '))-self.__new_property)
        
        self.__optimizer.register(params=next_point_to_probe, target=target)
    
    @property
    def get_x1_range(self):
        """
            Purpose : --> return int(__x1_range)
        """
        return self.__x1_range

    @get_x1_range.setter
    def get_x1_range(self, x1_range):
        """
            Purpose : --> get __x1_range to new __x1_range
        """
        self.__x1_range = x1_range
        
##################
#     Main.py    #
################### 

main_new_property = bo_object.get_new_property
main_optimizer = bo_object.get_optimizer
main_utility = bo_object.get_utility

해결방법은 간단하다.

 

method를 부르고, ()를 하지 않으면 된다.

 

즉, property로 감싼 method들은 call로 부르면 안 된다. 이 method들의 return과 행동들은 바로 적용되는 것이기 때문에, 당연히 call한다고 되지 않는다.

 

무슨말이냐면, 위의 method 중 get_new_property 를 실행하면, get_new_property 자체가 int를 의미하며, 100() 이렇게 숫자 뒤에 call하는 것과 동일하다고 생각하면 된다.

댓글