Python Forum
'namespace' shorthand for function arguments? - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: 'namespace' shorthand for function arguments? (/thread-34576.html)



'namespace' shorthand for function arguments? - shadowphile - Aug-10-2021

(using 3.9)
I tried to search for this subject but couldn't find the right wording (typical problem).
I have a function I am passing an object with attributes ('hand'). Hand has four attributes and I end up with dozens of references to those attributes by hand.this and hand.that.
What seems 'pythonic' would be a way to 'namespace' the argument for lack of a better word so I can just use 'this' and 'that'. For now I copied the four arguments into local variables, did all my work with those, then copied them back to the argument object. Here is my code with my klunky fix:
def updatevalue(hand):
    cards=hand.cards
    aceslow=hand.aceslow
    aceshigh=hand.aceshigh
    value=sum(cards)+(aceshigh*10) #for every aceshigh add 10
    while (value > 21) and (aceshigh > 0):  #lower aces until hand is <= 21 or no more aces
        aceshigh -= 1
        value -= 10
        aceslow += 1
        print(f'Current hand: {value}, aces high: {aceshigh}, aces low: {aceslow}')
    while aceshigh !=0 and value < 21:   #optional downgrades of remaining aces
        reply=input('Downgrade a remaining Ace?')
        if reply not in ('y','Y','n','N'):
            reply = 'y'
            print('Hunh? Try again, y or n.')
            continue
        elif reply.capitalize() =='Y':
            aceshigh -= 1
            value -= 10
            aceslow += 1
            continue
        else:
            break
    print('---------------------------------')
    print(f'Final hand: {value}, aces high: {aceshigh}, aces low: {aceslow}')
    hand.value = value
    hand.cards = cards
    hand.aceslow = aceslow
    hand.aceshigh = aceshigh
    return value



RE: 'namespace' shorthand for function arguments? - ndc85430 - Aug-10-2021

What, exactly, is wrong with having to write hand.value, for example?

It's a shame that you mutate hand instead of creating a new one, though (immutability is a really good idea - look up Rich Hickey's talk titled "The Value of Values" for a good explanation).


RE: 'namespace' shorthand for function arguments? - Gribouillis - Aug-10-2021

Usually it is not a problem to use a qualified name such as hand.aceshigh instead of just aceshigh and the trick used in your function indicates that the function should probably be rewritten some other way, for example by cutting it in smaller functions. For example you could do this
def user_approves(msg):
    while True:
        reply = input(msg).lower()
        if reply in ('y', 'n'):
            return reply == 'y'
        else:
            print('Hunh? Try again, y or n')

def updatevalue(hand):
    value = sum(hand.cards) + hand.aceshigh * 10
    while (
        (hand.aceshigh > 0) and
        ((value > 21) or user_approves('Downgrade a remaining Ace?'))):
        hand.aceshigh -= 1
        hand.aceslow += 1
        value -= 10
    print('---------------------------------')
    print(f'Final hand: {value}, aces high: '
          f'{hand.aceshigh}, aces low: {hand.aceslow}')
    return value
Notice that this code is shorter and better because we separated the interaction with the user from the main loop. More progress can be made because usually functions that don't print anything are more useful and reusable than functions that print something, but for this program it may be sufficient.

Just a comment about ndc85430's answer: note that Rich Hickey is the inventor of the Clojure language, a functional programming language related to Lisp. Functional programmers often convey a whole ideology of how programming really should be in the best of the worlds, but I don't think it is a good idea to suscribe blindly to these advices, especially if you are a procedural language's programmer. Immutability has many advantages but mutability has many advantages too. We all use mutable instances every day, so don't remake the world when you are just writing a game of cards!


RE: 'namespace' shorthand for function arguments? - deanhystad - Aug-10-2021

I understand the concern. By using lots of attributes in an object that was passed in as an argument your updatevalue method becomes strongly tied to the design of the cards class. This is not good for long term maintenance and it limits the usefulness of the function.

I don't think your problem is with using attributes of a class. I think updatevalue is poorly designed. A key tenet of software design is that each function has a well defined purpose. What is the purpose of updatevalue? Can you describe it in one or two short sentences?


RE: 'namespace' shorthand for function arguments? - buran - Aug-10-2021

In addition, updatevalue may well be a method of hand class


RE: 'namespace' shorthand for function arguments? - shadowphile - Aug-11-2021

(Aug-10-2021, 08:18 PM)deanhystad Wrote: I understand the concern. By using lots of attributes in an object that was passed in as an argument your updatevalue method becomes strongly tied to the design of the cards class. This is not good for long term maintenance and it limits the usefulness of the function.

I don't think your problem is with using attributes of a class. I think updatevalue is poorly designed. A key tenet of software design is that each function has a well defined purpose. What is the purpose of updatevalue? Can you describe it in one or two short sentences?

The decision tree for blackjack isn't very uniform and I realized at one point I needed a final value for a hand that could not be resolved based on the cards alone, but also required the user to make choices (in this case about downgrading Aces) and work later routines based on the final value alone.

I'm not a very good strategic thinker so doing a lot of up front planning for something even as simple as blackjack is an exercise in constantly learning where to draw the lines between what does where, AFTER I start programming.