views:

60

answers:

1

Hi everybody,

is this legal in python?. Seems to work ...

Thanks

# with these lines you not need global variables anymore

if __name__ == '__main__':
    import __main__ as main
else:
    main = __import__(os.path.basename(os.path.splitext(__file__)))

var_in_main = 0  # now any var is a global var, you can access any var from everywhere

def fun(*args, **kwargs):

    self = fun

    self.var_in_fun = 'I am a var into fun'

    if args:
        returnList = []
        for request in args:
            returnList.append( getattr(self, request , 'Sorry, no var named "%s" into fun.' % request ) )

        if len(returnList) == 1:
            return returnList[0]
        else:
            return returnList

    elif kwargs:
        for k,v in kwargs.iteritems():

            reset = kwargs.get('reset', None)
            if reset:
                main.var_in_main = 0

            if k == 'times':
                for i in range(v):
                    fun()

            setattr(self, k, v)

    else: # when no args or kwars, execute.
        main.var_in_main += 1
        print ' -', main.var_in_main
        return self


# testing 

print '\nSETTING AND GETTING VARS'

print '     ', fun('var_in_fun')
print '     ', fun('var_in_fun','erroneus_var_name')
print '     ', fun('var_in_fun','erroneus_var_name')[0]

fun( new_var_in_fun = fun )

print '     ', fun( 'new_var_in_fun' ) 
print '     ', fun

print '\nMULTIFUNCTION'



fun()()()()

fun()

fun()()()

print '\nRESET AND THEN LOOP'

fun( reset = 1)

fun( times = 3 )

print '\nRESET AND LOOP, IN ONE SHOT'

fun( reset= 1, times = 100  )

output

SETTING AND GETTING VARS
      I am a var into fun
      ['I am a var into fun', 'Sorry, no var named "erroneus_var_name" into fun.']
      I am a var into fun
      <function fun at 0x44f930>
      <function fun at 0x44f930>

MULTIFUNCTION
 - 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8

RESET AND THEN LOOP
 - 1
 - 2
 - 3

RESET AND LOOP, IN ONE SHOT
 - 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 - 24
 - 25
 - 26
 - 27
 - 28
 - 29
 - 30
 - 31
 - 32
 - 33
 - 34
 - 35
 - 36
 - 37
 - 38
 - 39
 - 40
 - 41
 - 42
 - 43
 - 44
 - 45
 - 46
 - 47
 - 48
 - 49
 - 50
 - 51
 - 52
 - 53
 - 54
 - 55
 - 56
 - 57
 - 58
 - 59
 - 60
 - 61
 - 62
 - 63
 - 64
 - 65
 - 66
 - 67
 - 68
 - 69
 - 70
 - 71
 - 72
 - 73
 - 74
 - 75
 - 76
 - 77
 - 78
 - 79
 - 80
 - 81
 - 82
 - 83
 - 84
 - 85
 - 86
 - 87
 - 88
 - 89
 - 90
 - 91
 - 92
 - 93
 - 94
 - 95
 - 96
 - 97
 - 98
 - 99
 - 100
+3  A: 
if __name__ == '__main__':
    import __main__ as main
else:
    main = __import__(os.path.basename(os.path.splitext(__file__)))

This is quite a fragile approach, since it relies on relative import behavior for all modules from within a package. There is a much better solution -- faster, more concise, and more reliable:

import sys
main = sys.modules[__name__]

The weird choice of main for the name remains (I normally use something like thismodule when I use this approach) but the approach taken to bind that name is now sound.

Alex Martelli
Clearly so much clean, thank you.What do you think about the 'pseudo-generator' behaviour of 'fun'?, maybe could be dangerous?.
Javier Garcia
@Javier, it's very bad style (one function doing many different jobs) and thus quite possibly buggy and hard to maintain, but offhand I don't see a specific "danger". (I'd never approve that bizarre code if I was tasked to review it, though;-). Anyway, it's quite a separate issue from using what you call `main` (and I prefer to call `thismodule`) in lieu of the `global` statement.
Alex Martelli