1

Hi im creating a program in python and im running into what i think might be unprofessional practice. so im aware global variables are almost never the answer or good news. but consider this function here.

Method 1:

def api_call_function(player_name):
    base_api = "https://secure.runescape.com/m=hiscore_oldschool/index_lite.ws?player="

    api_call = requests.get(base_api+player_name)

    return api_call.text

Imagine this function to be nested within quite a few functions and the function is ran somewhat regularly, so passing the base_api variable through as an argument would require passing it as an argument through many functions to reach this point.

Since pythons garbage collector works on the fly, assigning the base api string to a variable each time would waste memory and GC time. so the other options i have are not assigning it to a variable and just including it in the requests call such as the snippet below.

Method 2:

def api_call_function(player_name):

    api_call = requests.get("https://secure.runescape.com/m=hiscore_oldschool/index_lite.ws? 
                            player="+player_name)

    return api_call.text

Is this bad practice? or messy?

Should i use an alternative option of having the program run within the scope of a Class object so instead of using global variable or this method to store the base_api i can instead assign the base_api string to a static class variable and since the program would be within the scope of the class it would be able to access the base api, such as this.

Method 3:

class Program:
    base_api = "https://secure.runescape.com/m=hiscore_oldschool/index_lite.ws?player="

    def api_call_function(player_name):

        api_call = requests.get(Program.base_api+player_name)

        return api_call.text

Something like that.

What is the best practice when encountering this situation?

Thankyou in advance for providing insight into the best practices.

Simon L
  • 23
  • 4
  • "Global *variables* are almost never the answer or good news", but global *constants* are harmless. – Mechanic Pig Oct 17 '22 at 01:27
  • Ok so if i needed a list of player objects, would it be best to instantiate that list within a class if they are required to be used globally? – Simon L Oct 17 '22 at 17:21
  • It's very hard to say anything concrete without having the code to look at. Your question was about urls and now its about players - so it seems there isn't enough information now. I'd just say don't create a class merely because you think it is a "better way" - do it if it works. Do it another way if it makes more sense. – topsail Oct 17 '22 at 17:49
  • Okay thankyou, i didnt want to create another post if there was a simple answer to this but as you say its dependant on the rest of the code. Thankyou for your help though! – Simon L Oct 17 '22 at 18:12
  • You don't need to make your constant part of a class, you can make it part of a module instead. It will still be somewhat contained. – Mark Ransom Oct 18 '22 at 03:12

1 Answers1

2

My advice is to keep method 1 or use global constants.

First, point out a mistake:

Since pythons garbage collector works on the fly, assigning the base api string to a variable each time would waste memory and GC time.

No, it won't. Here I write a function at will as an example:

def method_1(player_name):
    base_api = "https://secure.runescape.com/m=hiscore_oldschool/index_lite.ws?player="
    return base_api + player_name

Check the compiled bytecode (my version is Python 3.10.8):

>>> dis(method_1)
  2           0 LOAD_CONST               1 ('https://secure.runescape.com/m=hiscore_oldschool/index_lite.ws?player=')
              2 STORE_FAST               1 (base_api)

  3           4 LOAD_FAST                1 (base_api)
              6 LOAD_FAST                0 (player_name)
              8 BINARY_ADD
             10 RETURN_VALUE

Note that the LOAD_CONST instruction is used here to load strings, which means that some optimizations are possible here. In fact, it only generates the string once and stores it in the function.__code__.co_consts:

>>> method_1.__code__.co_consts
(None, 'https://secure.runescape.com/m=hiscore_oldschool/index_lite.ws?player=')

Therefore, your concern is unnecessary. You can confidently use constants in functions.


Another possible choice is also contrary to your idea:

global variables are almost never the answer or good news

Global variables are really not a good choice, but the string object in Python is immutable. Therefore, as long as you do not use global statement in functions, the global string object is equivalent to a global constant, and using it will not harm your program. You can store them in the current namespace, or you can use another module to store global constants, depending on yourself.

For more information, please refer to Why are global variables evil?.

Mechanic Pig
  • 6,756
  • 3
  • 10
  • 31