[Tutor] global variables/constants versus volatile variables/constants

Albert-Jan Roskam fomcl at yahoo.com
Fri Jun 13 19:14:46 CEST 2014



----- Original Message -----

> From: Steven D'Aprano <steve at pearwood.info>
> To: tutor at python.org
> Cc: 
> Sent: Friday, June 13, 2014 3:08 PM
> Subject: Re: [Tutor] global variables/constants versus	volatile	variables/constants
> 
> On Fri, Jun 13, 2014 at 05:10:28AM -0700, Albert-Jan Roskam wrote:
> 
>>  The other day I used collections.namedtuple and I re-initialized 
>>  Record (see below) with every function*) call. Bad idea! It looks 
>>  nicer because I did not need a global (and globals are baaad, mkay?), 
>>  but it was *much* slower. I processed a log of a few million lines, I 
>>  think.
>> 
>>  # bad --> time-consuming
>>  import collections
>> 
>>  def do_something_with(raw_record):
>>     Record = collections.namedtuple("_", " 
> ".join("v%%03d" % i for i in range(100)))
>>     return Record(*raw_record.split())
> 
> Look at how much work you do here. First, you create a long string of 
> the form:
> 
>     "v000 v001 v002 v003 ... v099"
> 
> representing 1000 v-digits names. Then you create a brand new Record 
> class that takes those 100 v-digits names as arguments. Creating that 
> class requires building a string, parsing it as Python code, and then 
> running it. (You're not expected to know that, but if you read the 
> source code for namedtuple you will see that's how it works.) So 
> creating that class is slow. Every time you call the function, it builds 
> a new "v000 ... v099" string, from scratch, then builds a new class, 
> also from scratch, and finally populates an instance of that class with 
> 100 values from the raw_record.
> 
> Only that last step needs to be done inside the function.
 
Hmm, if I create the namedtuple with 'verbose=True' it *really* makes clear why it took so much longer.
(what's '_property' btw? I know 'property' and the newer decorator wih the same name, but not _property).

In [1]: import collections

In [2]: Record = collections.namedtuple("_", " ".join("v%03d" % i for i in range(100)),verbose=True)
class _(tuple):
    '_(v000, v001, v002, v003, v004, v005, v006, v007, v008, v009, v010, v011, v012, v013, v014, v015, v016, v017, v018, v019, v020, v021, v022, v023, v024, v025, v026, v027, v028, v029, v030, v031, v032, v033, v034, v035, v036, v037, v038, v039, v040, v041, v042, v043, v044, v045, v046, v047, v048, v049, v050, v051, v052, v053, v054, v055, v056, v057, v058, v059, v060, v061, v062, v063, v064, v065, v066, v067, v068, v069, v070, v071, v072, v073, v074, v075, v076, v077, v078, v079, v080, v081, v082, v083, v084, v085, v086, v087, v088, v089, v090, v091, v092, v093, v094, v095, v096, v097, v098, v099)'

    __slots__ = ()

    _fields = ('v000', 'v001', 'v002', 'v003', 'v004', 'v005', 'v006', 'v007', 'v008', 'v009', 'v010', 'v011', 'v012', 'v013', 'v014', 'v015', 'v016', 'v017', 'v018', 'v019', 'v020', 'v021', 'v022', 'v023', 'v024', 'v025', 'v026', 'v027', 'v028', 'v029', 'v030', 'v031', 'v032', 'v033', 'v034', 'v035', 'v036', 'v037', 'v038', 'v039', 'v040', 'v041', 'v042', 'v043', 'v044', 'v045', 'v046', 'v047', 'v048', 'v049', 'v050', 'v051', 'v052', 'v053', 'v054', 'v055', 'v056', 'v057', 'v058', 'v059', 'v060', 'v061', 'v062', 'v063', 'v064', 'v065', 'v066', 'v067', 'v068', 'v069', 'v070', 'v071', 'v072', 'v073', 'v074', 'v075', 'v076', 'v077', 'v078', 'v079', 'v080', 'v081', 'v082', 'v083', 'v084', 'v085', 'v086', 'v087', 'v088', 'v089', 'v090', 'v091', 'v092', 'v093', 'v094', 'v095', 'v096', 'v097', 'v098', 'v099')

    def __new__(_cls, v000, v001, v002, v003, v004, v005, v006, v007, v008, v009, v010, v011, v012, v013, v014, v015, v016, v017, v018, v019, v020, v021, v022, v023, v024, v025, v026, v027, v028, v029, v030, v031, v032, v033, v034, v035, v036, v037, v038, v039, v040, v041, v042, v043, v044, v045, v046, v047, v048, v049, v050, v051, v052, v053, v054, v055, v056, v057, v058, v059, v060, v061, v062, v063, v064, v065, v066, v067, v068, v069, v070, v071, v072, v073, v074, v075, v076, v077, v078, v079, v080, v081, v082, v083, v084, v085, v086, v087, v088, v089, v090, v091, v092, v093, v094, v095, v096, v097, v098, v099):
        'Create new instance of _(v000, v001, v002, v003, v004, v005, v006, v007, v008, v009, v010, v011, v012, v013, v014, v015, v016, v017, v018, v019, v020, v021, v022, v023, v024, v025, v026, v027, v028, v029, v030, v031, v032, v033, v034, v035, v036, v037, v038, v039, v040, v041, v042, v043, v044, v045, v046, v047, v048, v049, v050, v051, v052, v053, v054, v055, v056, v057, v058, v059, v060, v061, v062, v063, v064, v065, v066, v067, v068, v069, v070, v071, v072, v073, v074, v075, v076, v077, v078, v079, v080, v081, v082, v083, v084, v085, v086, v087, v088, v089, v090, v091, v092, v093, v094, v095, v096, v097, v098, v099)'
        return _tuple.__new__(_cls, (v000, v001, v002, v003, v004, v005, v006, v007, v008, v009, v010, v011, v012, v013, v014, v015, v016, v017, v018, v019, v020, v021, v022, v023, v024, v025, v026, v027, v028, v029, v030, v031, v032, v033, v034, v035, v036, v037, v038, v039, v040, v041, v042, v043, v044, v045, v046, v047, v048, v049, v050, v051, v052, v053, v054, v055, v056, v057, v058, v059, v060, v061, v062, v063, v064, v065, v066, v067, v068, v069, v070, v071, v072, v073, v074, v075, v076, v077, v078, v079, v080, v081, v082, v083, v084, v085, v086, v087, v088, v089, v090, v091, v092, v093, v094, v095, v096, v097, v098, v099))

    @classmethod
    def _make(cls, iterable, new=tuple.__new__, len=len):
        'Make a new _ object from a sequence or iterable'
        result = new(cls, iterable)
        if len(result) != 100:
            raise TypeError('Expected 100 arguments, got %d' % len(result))
        return result

    def __repr__(self):
        'Return a nicely formatted representation string'
        return '_(v000=%r, v001=%r, v002=%r, v003=%r, v004=%r, v005=%r, v006=%r, v007=%r, v008=%r, v009=%r, v010=%r, v011=%r, v012=%r, v013=%r, v014=%r, v015=%r, v016=%r, v017=%r, v018=%r, v019=%r, v020=%r, v021=%r, v022=%r, v023=%r, v024=%r, v025=%r, v026=%r, v027=%r, v028=%r, v029=%r, v030=%r, v031=%r, v032=%r, v033=%r, v034=%r, v035=%r, v036=%r, v037=%r, v038=%r, v039=%r, v040=%r, v041=%r, v042=%r, v043=%r, v044=%r, v045=%r, v046=%r, v047=%r, v048=%r, v049=%r, v050=%r, v051=%r, v052=%r, v053=%r, v054=%r, v055=%r, v056=%r, v057=%r, v058=%r, v059=%r, v060=%r, v061=%r, v062=%r, v063=%r, v064=%r, v065=%r, v066=%r, v067=%r, v068=%r, v069=%r, v070=%r, v071=%r, v072=%r, v073=%r, v074=%r, v075=%r, v076=%r, v077=%r, v078=%r, v079=%r, v080=%r, v081=%r, v082=%r, v083=%r, v084=%r, v085=%r, v086=%r, v087=%r, v088=%r, v089=%r, v090=%r, v091=%r, v092=%r, v093=%r, v094=%r, v095=%r, v096=%r, v097=%r, v098=%r, v099=%r)' % self

    def _asdict(self):
        'Return a new OrderedDict which maps field names to their values'
        return OrderedDict(zip(self._fields, self))

    __dict__ = property(_asdict)

    def _replace(_self, **kwds):
        'Return a new _ object replacing specified fields with new values'
        result = _self._make(map(kwds.pop, ('v000', 'v001', 'v002', 'v003', 'v004', 'v005', 'v006', 'v007', 'v008', 'v009', 'v010', 'v011', 'v012', 'v013', 'v014', 'v015', 'v016', 'v017', 'v018', 'v019', 'v020', 'v021', 'v022', 'v023', 'v024', 'v025', 'v026', 'v027', 'v028', 'v029', 'v030', 'v031', 'v032', 'v033', 'v034', 'v035', 'v036', 'v037', 'v038', 'v039', 'v040', 'v041', 'v042', 'v043', 'v044', 'v045', 'v046', 'v047', 'v048', 'v049', 'v050', 'v051', 'v052', 'v053', 'v054', 'v055', 'v056', 'v057', 'v058', 'v059', 'v060', 'v061', 'v062', 'v063', 'v064', 'v065', 'v066', 'v067', 'v068', 'v069', 'v070', 'v071', 'v072', 'v073', 'v074', 'v075', 'v076', 'v077', 'v078', 'v079', 'v080', 'v081', 'v082', 'v083', 'v084', 'v085', 'v086', 'v087', 'v088', 'v089', 'v090', 'v091', 'v092', 'v093', 'v094', 'v095', 'v096', 'v097', 'v098', 'v099'), _self))
        if kwds:
            raise ValueError('Got unexpected field names: %r' % kwds.keys())
        return result

    def __getnewargs__(self):
        'Return self as a plain tuple.  Used by copy and pickle.'
        return tuple(self)

    v000 = _property(_itemgetter(0), doc='Alias for field number 0')

    v001 = _property(_itemgetter(1), doc='Alias for field number 1')

    v002 = _property(_itemgetter(2), doc='Alias for field number 2')

    v003 = _property(_itemgetter(3), doc='Alias for field number 3')

    v004 = _property(_itemgetter(4), doc='Alias for field number 4')

    v005 = _property(_itemgetter(5), doc='Alias for field number 5')

    v006 = _property(_itemgetter(6), doc='Alias for field number 6')

    v007 = _property(_itemgetter(7), doc='Alias for field number 7')

    v008 = _property(_itemgetter(8), doc='Alias for field number 8')

    v009 = _property(_itemgetter(9), doc='Alias for field number 9')

    v010 = _property(_itemgetter(10), doc='Alias for field number 10')

    v011 = _property(_itemgetter(11), doc='Alias for field number 11')

    v012 = _property(_itemgetter(12), doc='Alias for field number 12')

    v013 = _property(_itemgetter(13), doc='Alias for field number 13')

    v014 = _property(_itemgetter(14), doc='Alias for field number 14')

    v015 = _property(_itemgetter(15), doc='Alias for field number 15')

    v016 = _property(_itemgetter(16), doc='Alias for field number 16')

    v017 = _property(_itemgetter(17), doc='Alias for field number 17')

    v018 = _property(_itemgetter(18), doc='Alias for field number 18')

    v019 = _property(_itemgetter(19), doc='Alias for field number 19')

    v020 = _property(_itemgetter(20), doc='Alias for field number 20')

    v021 = _property(_itemgetter(21), doc='Alias for field number 21')

    v022 = _property(_itemgetter(22), doc='Alias for field number 22')

    v023 = _property(_itemgetter(23), doc='Alias for field number 23')

    v024 = _property(_itemgetter(24), doc='Alias for field number 24')

    v025 = _property(_itemgetter(25), doc='Alias for field number 25')

    v026 = _property(_itemgetter(26), doc='Alias for field number 26')

    v027 = _property(_itemgetter(27), doc='Alias for field number 27')

    v028 = _property(_itemgetter(28), doc='Alias for field number 28')

    v029 = _property(_itemgetter(29), doc='Alias for field number 29')

    v030 = _property(_itemgetter(30), doc='Alias for field number 30')

    v031 = _property(_itemgetter(31), doc='Alias for field number 31')

    v032 = _property(_itemgetter(32), doc='Alias for field number 32')

    v033 = _property(_itemgetter(33), doc='Alias for field number 33')

    v034 = _property(_itemgetter(34), doc='Alias for field number 34')

    v035 = _property(_itemgetter(35), doc='Alias for field number 35')

    v036 = _property(_itemgetter(36), doc='Alias for field number 36')

    v037 = _property(_itemgetter(37), doc='Alias for field number 37')

    v038 = _property(_itemgetter(38), doc='Alias for field number 38')

    v039 = _property(_itemgetter(39), doc='Alias for field number 39')

    v040 = _property(_itemgetter(40), doc='Alias for field number 40')

    v041 = _property(_itemgetter(41), doc='Alias for field number 41')

    v042 = _property(_itemgetter(42), doc='Alias for field number 42')

    v043 = _property(_itemgetter(43), doc='Alias for field number 43')

    v044 = _property(_itemgetter(44), doc='Alias for field number 44')

    v045 = _property(_itemgetter(45), doc='Alias for field number 45')

    v046 = _property(_itemgetter(46), doc='Alias for field number 46')

    v047 = _property(_itemgetter(47), doc='Alias for field number 47')

    v048 = _property(_itemgetter(48), doc='Alias for field number 48')

    v049 = _property(_itemgetter(49), doc='Alias for field number 49')

    v050 = _property(_itemgetter(50), doc='Alias for field number 50')

    v051 = _property(_itemgetter(51), doc='Alias for field number 51')

    v052 = _property(_itemgetter(52), doc='Alias for field number 52')

    v053 = _property(_itemgetter(53), doc='Alias for field number 53')

    v054 = _property(_itemgetter(54), doc='Alias for field number 54')

    v055 = _property(_itemgetter(55), doc='Alias for field number 55')

    v056 = _property(_itemgetter(56), doc='Alias for field number 56')

    v057 = _property(_itemgetter(57), doc='Alias for field number 57')

    v058 = _property(_itemgetter(58), doc='Alias for field number 58')

    v059 = _property(_itemgetter(59), doc='Alias for field number 59')

    v060 = _property(_itemgetter(60), doc='Alias for field number 60')

    v061 = _property(_itemgetter(61), doc='Alias for field number 61')

    v062 = _property(_itemgetter(62), doc='Alias for field number 62')

    v063 = _property(_itemgetter(63), doc='Alias for field number 63')

    v064 = _property(_itemgetter(64), doc='Alias for field number 64')

    v065 = _property(_itemgetter(65), doc='Alias for field number 65')

    v066 = _property(_itemgetter(66), doc='Alias for field number 66')

    v067 = _property(_itemgetter(67), doc='Alias for field number 67')

    v068 = _property(_itemgetter(68), doc='Alias for field number 68')

    v069 = _property(_itemgetter(69), doc='Alias for field number 69')

    v070 = _property(_itemgetter(70), doc='Alias for field number 70')

    v071 = _property(_itemgetter(71), doc='Alias for field number 71')

    v072 = _property(_itemgetter(72), doc='Alias for field number 72')

    v073 = _property(_itemgetter(73), doc='Alias for field number 73')

    v074 = _property(_itemgetter(74), doc='Alias for field number 74')

    v075 = _property(_itemgetter(75), doc='Alias for field number 75')

    v076 = _property(_itemgetter(76), doc='Alias for field number 76')

    v077 = _property(_itemgetter(77), doc='Alias for field number 77')

    v078 = _property(_itemgetter(78), doc='Alias for field number 78')

    v079 = _property(_itemgetter(79), doc='Alias for field number 79')

    v080 = _property(_itemgetter(80), doc='Alias for field number 80')

    v081 = _property(_itemgetter(81), doc='Alias for field number 81')

    v082 = _property(_itemgetter(82), doc='Alias for field number 82')

    v083 = _property(_itemgetter(83), doc='Alias for field number 83')

    v084 = _property(_itemgetter(84), doc='Alias for field number 84')

    v085 = _property(_itemgetter(85), doc='Alias for field number 85')

    v086 = _property(_itemgetter(86), doc='Alias for field number 86')

    v087 = _property(_itemgetter(87), doc='Alias for field number 87')

    v088 = _property(_itemgetter(88), doc='Alias for field number 88')

    v089 = _property(_itemgetter(89), doc='Alias for field number 89')

    v090 = _property(_itemgetter(90), doc='Alias for field number 90')

    v091 = _property(_itemgetter(91), doc='Alias for field number 91')

    v092 = _property(_itemgetter(92), doc='Alias for field number 92')

    v093 = _property(_itemgetter(93), doc='Alias for field number 93')

    v094 = _property(_itemgetter(94), doc='Alias for field number 94')

    v095 = _property(_itemgetter(95), doc='Alias for field number 95')

    v096 = _property(_itemgetter(96), doc='Alias for field number 96')

    v097 = _property(_itemgetter(97), doc='Alias for field number 97')

    v098 = _property(_itemgetter(98), doc='Alias for field number 98')

    v099 = _property(_itemgetter(99), doc='Alias for field number 99')



<snip>


> Global variables aren't bad because Moses came down from the mountains 
> with a stone tablet that declares that they are bad. They're bad because 
> they cause excessive coupling, they operate by side-effect, they spoil 
> idepotent code, and they are implicit instead of explicit.


LOL :-) Textbooks conditioned me to have a generalized fear of globals. Like Little Albert: http://en.wikipedia.org/wiki/Little_Albert_experiment :-)




>>  def do_something_with(raw_record):
>>     return Record(*raw_record.split())
> 
> Much more sensible!
> 
> 
> 
> 
> -- 
> Steven



More information about the Tutor mailing list