0

I'm new to Python and I have factory class that takes in API arguments and with my setup i get a NameError: 'self' is not defined. I understand that my functions calls are wrong. How would I refactor this to have the same logic

import requests
import json

class Call:

    results = []
    __response = None
    __methods= dict(post=self.__post(), get=self.__get())


    def __init__(self, root, endpoint, payload, header):
        self.__root = root
        self.__endpoint = endpoint
        self.__payload = payload
        self.__header = header

    def __post(self):

       self.__response = requests.post(
            self.__root + self.__endpoint, 
            data = json.dumps(self.__payload), 
            headers = self.__header
        )

       self.__get_results()

    def __get(self):

       self.__response = requests.get(
            self.__root + self.__endpoint, 
            data = json.dumps(self.__payload), 
            headers = self.__header
        )

       self.__get_results()

    def __get_results(self):

        if (self.__response.ok):
            data = json.loads(self.__response.content)
            results.append(
                {
                    'result':data['result'], 
                    'endpoint': self.__endpoint, 
                    'status' : response.status_code
                }
            ) 
        else:
            results.append(
                {
                    'result':'FAILED', 
                    'endpoint': self.__endpoint, 
                    'status' : response.status_code
                }
            )

    def method(self, method):
        return self.__methods[method]

login = Call(
    Url.V1_PROD, 
    DriverEndpoint.LOGIN, 
    DriverPayload.LOGIN, 
    Request.HEADER
)

login.method('post')
martineau
  • 119,623
  • 25
  • 170
  • 301
teddybear123
  • 2,314
  • 6
  • 24
  • 38

2 Answers2

2

You shouldn't use variable names starting with a __double __underscore, they are used to invoke name mangling, which you probably don't want. Use a _single _underscore.

It's easier to declare your dictionary on the instance, in the __init__ method. A common alternative would be to store the names of the methods you want to call, as strings, and use getattr to access the methods (see Call a Python method by name).

import requests
import json

class Call:

    results = []
    _response = None


    def __init__(self, root, endpoint, payload, header):
        self._root = root
        self._endpoint = endpoint
        self._payload = payload
        self._header = header
        # NO () after self._post, otherwise it would call the
        # method and insert the return value in the dict
        self._methods= dict(post=self._post, get=self._get)

    def _post(self):

       self._response = requests.post(
            self._root + self._endpoint, 
            data = json.dumps(self._payload), 
            headers = self._header
        )

       self._get_results()

    def _get(self):

       self._response = requests.get(
            self._root + self._endpoint, 
            data = json.dumps(self._payload), 
            headers = self._header
        )

       self._get_results()

    def _get_results(self):

        if (self.__response.ok):
            data = json.loads(self.__response.content)
            results.append(
                {
                    'result':data['result'], 
                    'endpoint': self._endpoint, 
                    'status' : response.status_code
                }
            ) 
        else:
            results.append(
                {
                    'result':'FAILED', 
                    'endpoint': self._endpoint, 
                    'status' : response.status_code
                }
            )



    def method(self, method):
        # Here, we have to effectively call the selected method,
        # hence the () at the end
        self._methods[method]()

login = Call(
    Url.V1_PROD, 
    DriverEndpoint.LOGIN, 
    DriverPayload.LOGIN, 
    Request.HEADER
)

login.method('post')
Community
  • 1
  • 1
Thierry Lathuille
  • 23,663
  • 10
  • 44
  • 50
  • my intention of the double underscore was to make them private to the class. Wouldn't this be following best practices? – teddybear123 Feb 17 '17 at 19:46
  • see http://stackoverflow.com/questions/6930144/underscore-vs-double-underscore-with-variables-and-methods for a discussion of __. Short answer: don't use that. Single underscore is a *convention* that means that the method/attribute is for the internal usage of the class, or not supposed to be used from outside the class, or that it could change in the future.... In your code, there's no particular reason why one shouldn't use some of them directly (like post, for example, as method('post') doesn't do anything besides calling post – Thierry Lathuille Feb 17 '17 at 19:56
0
__methods= dict(post=self.__post(), get=self.__get())

Your __methods variable is class variable, self is used to refer to an instance of Call, self cannot access to the class variable scope.

You can declare __method as an instance variable:

def __init__(self):
    self.__methods= dict(post=self.__post(), get=self.__get())

def get_mothods(self):
    return self.__methods
Haifeng Zhang
  • 30,077
  • 19
  • 81
  • 125