1

I am trying convert my program to an object orientated style. Currently, I have a brandSelector() function which takes the query input and finds an intersection between the query and the brands array. However, I am trying to convert the brandSelector() to a generic Selector() or intersection finder. For example, I could call with type and the query (Selector(type, query)). In this instance you would type Selector(brand, query). That additional parameter defines which array is checked and which variable is set - alternatively, an if statement would suffice - but I am not sure how to implement such a system. I would appreciate any solutions or advice. Thanks,

brands = ["apple", "android", "windows"]
brand = None

def Main():
    query = input("Enter your query: ").lower()
    brand = brandSelector(query)

def brandSelector(query):
    try:
        brand = set(brands).intersection(query.split())
        brand = ', '.join(brand)
        #Check Condition After Setting
        int_cond = confirmIntersection(brand)
        if int_cond == False:
            raise NameError("No Intersection")
        return brand
    except NameError:
        print("\nNo Intersection found between query defined brand and brands array\n")
        return brandDetectionFailure()

Full Code: https://github.com/KentCoding/phoneTroubleshooting/blob/master/phoneTroubleshooting.py Python Version: v3.5.2

My Attempt:

def Main():
    init()
    query = input("Enter your query: ").lower()
    brand = Selector(brand, brands, query)
    keywordSelection(query, brand)
def Selector(var, array, query):
    try:
        #Format Brands Query
        var = set(array).intersection(query.split())
        var = ', '.join(var)
        #Check Condition After Setting
        int_cond = confirmIntersection(var)
        if int_cond == False:
            raise NameError("No Intersection")
        return var
    except NameError:
        print("\nNo Intersection found between query defined brand and brands array\n")
        return brandDetectionFailure()

But gives the error: UnboundLocalError: local variable 'brand' referenced before assignment

martineau
  • 119,623
  • 25
  • 170
  • 301
  • The error is because the statement `brand = Selector(brand, brands, query)` attempts to use `brand` by passing it as an argument to the `Selector()` function before it's defined. – martineau Aug 21 '16 at 00:06
  • Surely, it would not be a problem as I have defined it as a global with `brands = ["apple", "android", "windows"] brand = None` However, if this does not work, how may I fix it? Thanks for your help – Sammy Herring Aug 21 '16 at 00:07
  • 1
    Legend - Thank you! :-) If you put it as an answer, I'm happy to give it a tick if you would like the rep points. – Sammy Herring Aug 21 '16 at 00:12

1 Answers1

1

From what I can see, there's no reason to have the argument named var being passed to Selector(), so just make it def Selector(array, query): and call it with brand = Selector(brands, query).

martineau
  • 119,623
  • 25
  • 170
  • 301
  • You're welcome. BTW, inside the `main()` function `brand` is considered to be a local variable because it's being assigned a value (the result of calling `Selector()`) and there's no preceding `global brand` statement before that point in the function. – martineau Aug 21 '16 at 00:19
  • Thanks for the tip :-) – Sammy Herring Aug 21 '16 at 00:22
  • IMO It's a bit more than a "tip" because it's important to understand that Python is executing your `def` before the byte code generated from doing that is itself ever executed. This means that when it encountered the `Selector(brand, brands, query)` call all it knew was that the variable `brand` had not been declared `global` (so it must be local) and had not been bound to [i.e. assigned] a value yet. – martineau Aug 21 '16 at 00:35
  • Does this mean you cannot simply define a global outside any of the functions? Therefore, you must reference the global within the function? If so, how? Thanks – Sammy Herring Aug 21 '16 at 00:49
  • Also, as a Python expert, you wouldnt know if it is possible to print a array's variable name having assigned an array using a variable, for example: brands = ["apple", "android", "windows"] In this instance print `'brands'` rather than `'["apple", "android", "windows"]'` Thanks, – Sammy Herring Aug 21 '16 at 00:56
  • Using a `global` statement outside a function or method doesn't do anything (although no error message occurs). All variables assigned a value in a function will cause a local variable to be created if it doesn't already exist. To prevent this, you must declare it as a `global` in the function before any such assignment takes place—so I guess that counts as the "reference" you're talking about. – martineau Aug 21 '16 at 01:04
  • Printing `brands` is a reference—not an assignment—to it, so Python resolves its value using the [LEGB Rule](http://stackoverflow.com/questions/291978/short-description-of-python-scoping-rules/292502#292502). – martineau Aug 21 '16 at 01:08
  • Ok - that makes sense. It is very kind of you for providing such a level of depth. Thank you. May I ask how you could then print the variable name of an array? – Sammy Herring Aug 21 '16 at 01:24
  • Values don't know what their names are (they may have more than one or even be anonymous, in fact). There are some hacks that can look for a name associated with a given value in the various LEGB scopes, but it's generally considered a poor practice. You could pass the variable name as a hardcoded string to `Selector()` as another argument if you wished. – martineau Aug 21 '16 at 03:53
  • Great, thank you - I will try it as an argument. Thanks – Sammy Herring Aug 21 '16 at 10:59
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/121464/discussion-between-sammy-herring-and-martineau). – Sammy Herring Aug 21 '16 at 12:56