<txp:article status="sticky" limit=1 /> ->  Textpattern Warning: Die Werte für Attribute müssen in Hochkommata eingeschlossen werden  on line 916
textpattern/lib/txplib_misc.php:916 trigger_error()
textpattern/publish.php:1090 splat()
textpattern/publish.php:1012 processTags()
textpattern/publish.php:496 parse()
index.php:33 textpattern()
Peterpedia-Flash: python &#38; other sloppy hacks
Übersicht Peterpedia lesen What's up Peterpedia? Administration Suche

Make special keys Just Work · 1092 Tage zuvor von stargaming

I’m using a “Wireless Desktop Edge” from Labtec (image, large). I haven’t cared about the special keys so far (after migrating to Linux), but after a while the mouse became really inconvenient.

Notice: I’m doing this under Sidux (Linux 2.6.22.1-slh-smp-2 #1 SMP PREEMPT Wed Jul 11 01:45:29 CEST 2007 i686 GNU/Linux), KDE-full. YMMV.

Getting keycodes

Retrieving a keycode to a button on the keyboard is pretty trivial. Start the application xev and press whatever button you’d like to know about. Run it in a terminal because the information will go to the console. Close the window when you’re done (or press Ctrl+C).

Along those lines, the latter ones will be the most interesting ones for you (this is the event for my shutdown/hibernate key):

KeyPress event, serial 29, synthetic NO, window 0x3600001,
    root 0x1a5, subw 0x3600002, time 826747352, (51,47), root:(55,831),
    state 0x0, keycode 223 (keysym 0x0, NoSymbol), same_screen YES,
    XLookupString gives 0 bytes:
    XmbLookupString gives 0 bytes:
    XFilterEvent returns: False

The keycode is in line 3, if you’ve overseen it.

If you’re too lazy to do this yourself, I can give you my results:

key keycode
Play/Pause 162
Stop 164
Previous 144
Next 153
Mute 160

Linking the keycode to a symbolic name

In this step, we’ll utilize the xmodmap tool. There is a good howto from David Vespe, Remapping Keys, but the manual page should be enough for everyone.

For a quick introduction, there is that keycode and there is a “keysym”, a symbolic name for the key. Basically, you can use any symbolic name defined in /usr/include/X11/keymapdef.h (without the KX_ prefix). I found this group symbolic key names for the 3270 terminal and since it wasn’t in use, I took that one. You could overwrite the “Japanese Keyboard Support”, “Braille” or “Vietnamese” as well, I guess.

#define XK_3270_Quit                     0xfd09
#define XK_3270_Jump                     0xfd12
#define XK_3270_Play                     0xfd16
#define XK_3270_DeleteWord               0xfd1a
#define XK_3270_ExSelect                 0xfd1b

I took those because I found these names most… symbolic for the keys. ;)

key keycode keysym
Play/Pause 162 3270_Play
Stop 164 3270_Quit
Previous 144 3270_ExSelect
Next 153 3270_Jump
Mute 160 3270_DeleteWord

You can try mapping keycode to keysym with xmodmap -e, as in:

$ xmodmap -e "keycode 162 = 3270_Play"
$ xmodmap -e "keycode 164 = 3270_Quit"
$ xmodmap -e "keycode 144 = 3270_ExSelect"
$ xmodmap -e "keycode 153 = 3270_Jump"
$ xmodmap -e "keycode 160 = 3270_DeleteWord"

If you go to any KDE application that supports “Global Shortcuts” now, you’ll actually find a reaction to those keys.

Mapping permanently

Now, there are several ways to run those xmodmap commands once per session. But the most convenient is, in my opionion, modifying /etc/X11/Xsession/ to invoke xmodmap ~/.xmodmap at the start of an X session.


XMODMAPFILE=$HOME/.xmodmap
if [ -f $XMODMAPFILE ]; then
    xmodmap $XMODMAPFILE
fi

Now, this will source the .xmodmap file in your home directory. You can just fill this with the arguments you gave to xmodmap -e.

keycode 162 = 3270_Play
keycode 164 = 3270_Quit
keycode 144 = 3270_ExSelect
keycode 153 = 3270_Jump
keycode 160 = 3270_DeleteWord

Alternative mapping

If you haven’t got root access, you can perhaps just edit your .Xsession, .xsession or .loginrc (first two confirmed in my /etc/X11/Xsession, latter one from a 10 years old internet source). The line xmodmap $HOME/.xmodmap should be enough in there.

KDE startup manager (updated)

I might have been kinda mislead about the persistance/invokation on KDE. It seems you rather have to edit /etc/kde*/kdm/Xsession. If you cannot edit this document, a file based on your shell might work, too:

shell location
bash 1 $HOME/.bash_profile $HOME/.bash_login $HOME/.profile
zsh 2 $zdir/zprofile $zhome/.zprofile $zdir/zlogin $zhome/.zlogin
csh/tcsh /etc/csh.login ~/.login
* /etc/profile $HOME/.profile

1: only the first existing file in this list is sourced.
2: $zdir is /etc/zsh or /etc, $zhome is ${ZDOTDIR:-$HOME}

Your shell will be determined by your $SHELL variable.

Artikel bearbeiten

Kommentieren

Support in Bugtrackern · 1108 Tage zuvor von stargaming

Manchmal frage ich mich, welche Leute Bugtracker entwerfen.

Bugtracker, das sind spezielle Internetformulare um Fehler in einer Software zu melden. Meist wird die gleiche Prozedur auch als Wunschliste (“Feature Request”) verwendet und man kann häufig, neben der Problembeschreibung auch einen passenden Patch einsenden.

Die meisten Tracker sind leider hoffnungslos überladen und die Entwickler kommen einfach nicht hinterher — die meisten Patches verrotten sogar.

Wenn dann aber bei jedem x-beliebigen Bugtracker von einem 5-Mann-Projekt (kommt mir also bitte nicht mit den bösen Spammern…) eine Registration erforderlich ist, vergeht mir echt die Lust, noch irgendwie mitzuhelfen. Wozu denn der Unfug?

Artikel bearbeiten

Kommentieren

Making of "Spam: Leihgaben ausgewertet" · 1141 Tage zuvor von stargaming

Die tolle Grafik in Spam: Leihgaben ausgewertet wurden anhand dieses Codeschnipsels erstellt.

Ich hab’s mit Python 2.5 getestet. Dazu braucht man noch Matplotlib zum Plotten.

Die Daten werden aus Mbox-Dateien extrahiert — solche legt z. B. Thunderbird im Benutzerordner an. In der aktuellen Einstellung werden da einfach nur alle Beträge in Dollar rausgelesen.

Benutzt wird das Programm mit keinen Programmparametern (dann erwartet es die Daten in der Datei “Test”), sonst kann auch die Quelldatei über die Befehlszeile angegeben werden. Ausgabe passiert immer nach “loans.png”. Die Transparenz (wie im Artikel) habe ich mit Gimp nachgebessert, da ich sonst noch PIL (Python Imaging Library) oder sonstiges benutzen hätte müssen.

python:
  1. #!/usr/bin/env python
  2. # encoding: utf-8
  3. #
  4. #
  5.  
  6. from __future__ import with_statement, division
  7.  
  8. # logging
  9. from logging import *
  10. basicConfig(level=DEBUG,
  11.             datefmt='%M:%S',
  12.             format='%(relativeCreated)05d %(levelname)8s: %(message)s')
  13. debug('Enabled log.')
  14.  
  15. # reading mbox-format Mailboxes (Mozilla/Netscape)
  16. debug('Loading mailbox reader..')
  17. from mailbox import mbox
  18.  
  19. # parsing utilites
  20. debug('Loading email parsers..')
  21. import datetime as _dt
  22. _strptime = _dt.datetime.strptime
  23. from re import compile as _compile
  24. from operator import itemgetter as _item
  25. from collections import defaultdict as _dict
  26.  
  27. # plotting framework
  28. debug('Loading plotting framework..')
  29. import pylab
  30.  
  31. info('All packages included.')
  32.  
  33. money = _compile(r'''\$(\d{1,3}),000''')
  34. avg = lambda *a:sum(a) // len(a)
  35.  
  36. def main(path):
  37.     info('Opening mbox..')
  38.     repo = mbox(path)
  39.     info('Creating database..')
  40.     loan = _dict(list)
  41.     info('Parsing %d emails..', len(repo))
  42.     for mail in repo.itervalues():
  43.         amount = money.search(mail.as_string())
  44.         if amount:
  45.             date = _strptime(mail.get_from(), '- %a %b %d %H:%M:%S %Y')
  46.             amount = int(amount.group(1).replace(',', ''))
  47.             loan[date].append(amount)
  48.     del repo
  49.     info('Matched %d emails.', len(loan))
  50.     info('Building an average value of every date..')
  51.     loanavg = list()
  52.     for date, amounts in loan.iteritems():
  53.         loanavg.append((date, avg(*amounts)))
  54.     del loan
  55.     info('Sorting results..')
  56.     loanavg.sort(key=_item(0))
  57.     info('Extracting information..')
  58.     x, y = zip(*loanavg)
  59.     x = pylab.date2num(x)
  60.     del loanavg
  61.  
  62.     info('Plotting %d dates..', len(x))
  63.     debug('Drawing first plot..')
  64.     pylab.xlabel('date')
  65.     pylab.ylabel('loan in $1000')
  66.     pylab.plot_date(x,
  67.                     y,
  68.                     xdate=True,
  69.                     linestyle='-',
  70.                     markersize=0.01,
  71.                    )
  72.     pylab.axis('tight')
  73.  
  74.     info('Saving plot to file..')
  75.     pylab.savefig('loans.png', facecolor='white')
  76.     info('Showing plot..')
  77.     pylab.show()
  78.  
  79.  
  80. if __name__ == '__main__':
  81.     from sys import argv
  82.     if len(argv) >= 2:
  83.         main(' '.join(argv[1:]))
  84.     else:
  85.         main('Test')

Artikel bearbeiten

Kommentieren

A bug in matplotlib? · 1168 Tage zuvor von stargaming

I’m just abusing this place to temporarily store the bug report, going to submit it to matplotlib’s bug tracker later.

>>> from pylab import *
>>> plot([1], [1])
[<matplotlib.lines.Line2D instance at 0x013A1378>]
>>> plot([1], [1])
[<matplotlib.lines.Line2D instance at 0x013A13F0>]
</txp:krl_geshiSyntaxHighlight>

python:
  1. >>> from pylab import *
  2. >>> plot_date([1], [1])
  3. []
  4. >>> plot_date([1], [1])
  5. """
  6. Traceback (most recent call last):
  7.   File "", line 1, in
  8.   File "python25\lib\site-packages\matplotlib\pylab.py", line 2064, in plot_date
  9.     ret =  gca().plot_date(*args, **kwargs)
  10.   File "python25\lib\site-packages\matplotlib\axes.py", line 2397, in plot_date
  11.     self.xaxis_date(tz)
  12.   File "python25\lib\site-packages\matplotlib\axes.py", line 1566, in xaxis_date
  13.     formatter = AutoDateFormatter(locator)
  14. UnboundLocalError: local variable 'locator' referenced before assignment
  15. """

patch to matplotlib\axes.py

1560a1561,1562
>         else:
>             locator = thislocator
Artikel bearbeiten

Kommentieren

Struggling with Ubuntu · 1169 Tage zuvor von stargaming

I am (again, as some of you might know) struggling with a *nix install on my machine, trying Ubuntu Feisty Fawn (7.04) this time. To share my experiences on the one hand, and to receive some help on the other one, I will write down my progress and efforts so far.

First, you should note that I’m running a AMD Athlon 64 3000+. As far as I explored, all my hardware is ok and appropriate (I’m running Windows on it successfully). Memtest86+ passed without any errors (didn’t try it for a longer period of time but my Windows is running just fine for 2 or 3 days).

32 bit install

Okay, let’s start. I tried to install Ubuntu 7.04 i386 (right, 32 bit, I didn’t want to do without Flash and all this 32 bit pre-ancient stuff) and failed miserably. I got something like the following:

Int 14: CR2 f8000000 err 00000000 EIP c020c384 CS 00000000 flags 00010007

After investigating some time into Google searches, I could only come up with “Flash your BIOS”. Since I’m pretty uncomfortable with harming my computer (yes, a little bit of paranoia here), I’d like to keep this as a very last option. (And as I also read that for some people, this didn’t change anything, I’m not going to try it myself at the moment.)

Ah — if you want sources, just try a quick Google search, I’m refering to the top 10 results mostly.

My first thought was, Whoops! Perhaps, 32 bit does not work that good on amd64 at last? Our funny journey continues.

As a sidenote: I came to the selection screen. This worked all fine, but when I chose “Run or install Ubuntu”, it error’d.

For all those who keep suggesting a BIOS flash: a) My paranoia will drive me nuts if I even consider this one! b) Other people had no success with it. c) It was just some random note from the world wide web and has been documented to work just once. This is no good evidence to make it a general solution. c) Dated BIOS on an amd64? You’re kidding, aren’t you?

64 bit install

Downloaded Ubuntu 7.04 for amd64 machines, burned it to a disk, inserted it into my cdrom, hoping to see a goddamn linux finally, failed again:

Kernel alive
Kernel direct mapping tables up to 100000000 @ 8000-d000
PANIC: early exception rip ffffffff8035c819 error 0 cr2 ffff810040000000

Googled again with a bit more success now. There were several results, either cross-linking to the “Flash your BIOS” thread or suggesting some boot options.

Boot options

acpi=off noapic nolapic
mce=off acpi=off pci=conf1
noacpi=noapm

These were the three main suggestions ol’ mailing list archives gave me.

Note: There is a SuSE distribution installed on my machine. I didn’t install it myself, though, and it freezes occasionally. See below for details.

This matched a recommendation of the person who installed a linux version on this machine and told me he had some trouble with ACPI, too.

However, neither removing quiet nosplash nor adding one of the switches (I even tried to combine them all!) fixed the installation, regardless of the number of bits. I saw a nice text console that gave me lots of warnings like about misallocations on IRQ 0 or something like that (sorry, I could neither read, nor memorize nor scroll up (any hints how to scroll up in these 50% consoles?) fast enough) but it always stopped while * Loading hardware drivers. (If someone helps me to scroll up (no, it obviously isn’t PgUp/PgDown), I could supply additional information.)

Diving into BIOS

As of a hint of the previous maintainer, that pointed towards disabling ACPI, I started my (rather badly computer-translated BIOS (I’m german, as some may have noticed) ;)) BIOS setup. In the Energy (I’m retranslating them for easier comprehension) tab, there were two adequate entries:

ACPI Suspend Type [S1&S3]
ACPI APIC support [Deactivated]

No other mentions of ACPI. If you need further information, I’m happy to supply my BIOS’ version.

Help!

If you got any hints, feel free to use the comment form or write an email to stargaming (at) gmail (.) com. Thank you.

scroll up shift+bildauf/bildab — ChosenOne (“bildauf” means PgUp, “bildab” means PgDown)

32 bit alternate install

Just (one day later) tried Ubuntu 6.10’s 32 bit alternate version (for all those who aren’t comfortable with the normal installation). Guess what — failed again.

Unknown interrupt or fault at EIP 00000060 c0100231 00000230

Google yields a number of results this time, mostly pointing towards a broken disk. However, I won’t waste another blank CD except anyone will convince me that those alternative installs have a chance to fix my problems.

Retry alternatives.

Welcome again to our show. Our last episode terminated with “EPIC FAIL” (4chan-insider, sorry).

I’m writing the following report like one and a half month after it happened. I might mix some events up, be unable to read my handwritings whilst installation or not remember what actually happened, however, just keep in mind: It. Did. Not. Work. At all. (It not “just works”, geez!)

So, I retried the latest alternate disk and it even kinda worked. I tried pci=conf1, noacpi and noapic and all resulted in an interrupt 14. With acpi=off I could — attention now, dear audience — enter the textmode install. It threw some mysterious (apparently not too bad) exceptions about IRQ #11.

When in hardware initialization mode, these wonderful messages popped up:

ata: SATA link up 1.5 Gbps (status 113 control 300 qc timeout)
failed to set xfermode
speed UDMA
failed to recover some devices, retrying in 5 seconds

This procedure repeated about 6 times (connected with some CD acticity) and finally resulted in a textmode install. If you’re young and naive, you could think (or yell) now, “Oh, it worked! That’s wonderful, go on with the textmode and install Ubuntu. Finally.”

You failed. I went through the setup — ecstatic to the limit — and finally came through partitioning. “So, where will I put my Ubuntu now? The 120 Gb disk or the 80 Gb one?” But that’s not at all what the setup asked. It was “120 Gb hdd. Ok?!” No, damn, that was not okay at all!

That’s it again. I aborted the installation, unplugged the CD and rebooted Windows. “It just works.”

If you’re interested, I also had to switch the CD over to another drive because the slave one threw an Incorrect CD-ROM detected error. Just another whack of my weird, weird computer setup.

Why not another Debian?

Hello and welcome back. Due to some recent recommendations, I tried Sidux, another Debian derivate. And you can believe me or not, it worked. I started it up in normal mode (there are quite a few options for debugging erroneous machines — perhaps gonna try those later) with a nice KDE desktop and a console and internet access and all this stuff.

Unfortunately, the disk setup didn’t work, again. It just recognized this one hdd and I really don’t want to install it there.

I was unabled to find any dmesg, /var/log was all over populated with empty files (except some binary junk).

Plans

So, I got a few new plans and if you’d like to support me, you could tell me some advantages/disadvantages about them or even suggest other actions.

First, I will try the other boot options of Sidux. Probably their hardware diagnostics are good enough to get my machine to work.

If this all won’t work, I will perhaps try to unplug some hardware devices. I emphasize perhaps because, as I stated before, I really, really, really got some kind of technophobia. All this stuff is fine, I know how it works, theory is okay. But touching it? Uh — never! “Never touch a running system.”

Thank you for reading so far.

IT JUST WORKS

Wow. Sidux works when started in the ‘noapic’ mode. I can finally access all hdds and install it. End of the story.

Appendix A — Hardware details

Artikel bearbeiten

Kommentieren [2]

Mirroring · 1209 Tage zuvor von stargaming

Dank Armin Ronacher (der mich auf den entscheidenden Tipp gebracht hat, Informationen einfach in einem Funktionsattribut zu speichern), ist folgendes Codeschnipselchen entstanden:

python:
  1. class Mirroring(type):
  2.     def __new__(meta, name, bases, clsdict):
  3.         for key, value in clsdict.items():
  4.             if hasattr(value, 'func_code') and hasattr(value, '_mirroring'):
  5.                 for mirror in value._mirroring:
  6.                     for alias in mirror[0]:
  7.                         if alias not in clsdict:
  8.                             clsdict[alias] = lambda *a, **k: value(*a, **k)
  9.                             clsdict[alias].__name__ = alias
  10.                             if mirror[1]:
  11.                                 clsdict[alias].doc = mirror1
  12.                             else:
  13.                                 clsdict[alias].__doc__ = \
  14.                                     getattr(value, '__doc__', None)
  15.         return type.__new__(meta, name, bases, clsdict)
  16.  
  17. def mirror(*names, **doc):
  18.     def wrapped(f):
  19.         if not hasattr(f, '_mirroring'):
  20.             f._mirroring = []
  21.         f._mirroring.append((names, doc.get('doc', None)))
  22.         return f
  23.     return wrapped

Benutzt wird es in etwa so:

python:
  1. class A(object):
  2.   __metaclass__ = Mirroring
  3.   @mirror("bar", doc="abkuerzung fuer foo")
  4.   def foo(self):
  5.     "irgendeine wichtige methode"
  6.     print "hi!"
  7. a = A()
  8. a.foo() # hi!
  9. a.bar() # hi!
  10. print a.foo.__doc__ # irgendeine wichtige methode
  11. print a.bar.__doc__ # abkuerzung fuer foo

Mirroring muss als Metaklasse gesetzt werden, um das Injizieren der Aliase zu ermöglichen. mirror nimmt als Argumente arbiträr viele positionale Namen auf die gespiegelt wird und eine Schlüsselwortargument doc (andere werden verschluckt), welches die Dokumentation ergibt.

Nützlich ist das zum Beispiel in cmd.Cmd, wo jeder Befehl der Kommandozeile mit einer Methode do_Befehl registriert wird.

python:
  1. __metaclass__ = Mirroring
  2. class Cmd(cmd.Cmd):
  3.   @mirror('do_q', doc='shorthand for quit')
  4.   def do_quit(self):
  5.     exit()

Artikel bearbeiten

Kommentieren

PyPy erfindet nebenbei geile Syntax · 1216 Tage zuvor von stargaming

Das PyPy 1.0 draußen ist, dürfte ja mittlerweise die Runde gemacht haben (Jacob Hallen zu PyPy).

Jedenfalls ist mir beim Durchstöbern der Bibliotheken dort etwas Spaßiges aufgefallen:

python:
  1. class __extend__(IrgendeineAndereKlasse):
  2.   def angehangeneMethode(self):
  3.     ...

Das Ganze geht zurück auf eine sehr schöne Metaklasse (die auf IrgendeineAndereKlasse angewendet werden muss):

python:
  1. """
  2.     class X:
  3.         __metaclass__ = extendabletype
  4.         ...
  5.  
  6.     # in some other file...
  7.     class __extend__(X):
  8.         ...      # and here you can add new methods and class attributes to X
  9. """
  10.  
  11. class extendabletype(type):
  12.     """A type with a syntax trick: 'class __extend__(t)' actually extends
  13.     the definition of 't' instead of creating a new subclass."""
  14.     def __new__(cls, name, bases, dict):
  15.         if name == '__extend__':
  16.             for cls in bases:
  17.                 for key, value in dict.items():
  18.                     if key == '__module__':
  19.                         continue
  20.                     setattr(cls, key, value)
  21.             return None
  22.         else:
  23.             return super(extendabletype, cls).__new__(cls, name, bases, dict)

Was es erlaubt, Klassen in anderen Dateien als der Deklarationsdatei zu “erweitern” (ja, es ginge auch über die Zuweisung Klasse.methode = ..., ist aber lange nicht so schön).

Speziell kommt das aus der Datei pypy/tool: pairtype.py.

Artikel bearbeiten

Kommentieren

Postfix type declarations · 1217 Tage zuvor von stargaming

Der beste Aprilscherz (abgesehen von unserem und bereits erwähnten) ist Georg Brandls Vorschlag der Unicode Postfix type declarations.

Nachtrag: Haah, Python on Planes.

Ausschnitte

Python has long suffered from the lack of explicit type declarations. [...]
Unicode makes it possible to express much more with much less characters, which is in accordance with the Zen (“Readability counts.”). Additionally, it eliminates the need for a separate type declaration statement, and last but not least, it makes Python measure up to Perl 6, which already uses Unicode for its operators. [...]

When the type declaration mode is in operation, the grammar is changed so that each NAME must consist of two parts: a name and a type declarator, which is exactly one Unicode character.
The declarator uniquely specifies the type of the name, and if it occurs on the left hand side of an expression, this type is enforced: an InquisitionError exception is raised if the returned type doesn’t match the declared type. [...]

The mapping between types and declarators is not static. It can be completely customized by the programmer, but for convenience there are some predefined mappings for some built-in types:

object (REPLACEMENT CHARACTER)
int (DOUBLE-STRUCK CAPITAL N)
float (ESTIMATED SYMBOL)
bool (CHECK MARK)
tuple (PARENTHESIZED LATIN SMALL LETTER T)
dict (DOUBLE-ENDED MULTIMAP)
set (EMPTY SET)
function ƛ (LATIN SMALL LETTER LAMBDA WITH STROKE)

The declarator for the None type is a zero-width space.
These characters should be obvious and easy to remember and type for every programmer. [...]

Since even in our modern, globalized world there are still some old-fashioned rebels who can’t or don’t want to use Unicode in their source code, and since Python is a forgiving language, a fallback is provided for those:
Instead of the single Unicode character, they can type name${UNICODE NAME OF THE DECLARATOR}$. [...]

The encoding in which the code is written is read from a standard coding cookie. There will also be an autodetection mechanism, invoked by from __future__ import encoding_hell.

Artikel bearbeiten

Kommentieren

double negation, anyone? · 1244 Tage zuvor von stargaming

While discussing the introduction of a bool keyword to Python because not is a keyword, too, we (you may consider this either as ‘we, our majesty’ or ‘we, the python folks’) came up with a funny observation: our getattribute-mechanism sucks.

Well, I just fooled you. Semantically and when in use, it’s pure ownage. But it’s speed — aww! Not as if python programmers were speed zealots (“If I uglify my source code enough, it’ll be 0.001ms faster, yeeha!”), but it’s an historic semi-issue that getattr is — because of the comfortability of python’s attribute mechanism — slow. But since no one addresses it, it’s not a real issue.
I will illustrate this with the example mentioned above, the bool discrimination and how to more or less solve it: Double negation. :-)

First, watch this:

python:
  1. >>> import dis
  2. >>> def foo():
  3. ...   not not 5
  4. ...
  5. >>> dis.dis(foo)
  6.   2           0 LOAD_CONST               1 (5)
  7.               3 UNARY_NOT
  8.               4 UNARY_NOT
  9.               5 POP_TOP
  10.               6 LOAD_CONST               0 (None)
  11.               9 RETURN_VALUE
  12. >>> def foo():
  13. ...   bool(5)
  14. ...
  15. >>> dis.dis(foo)
  16.   2           0 LOAD_GLOBAL              0 (bool)
  17.               3 LOAD_CONST               1 (5)
  18.               6 CALL_FUNCTION            1
  19.               9 POP_TOP
  20.              10 LOAD_CONST               0 (None)
  21.              13 RETURN_VALUE

You can mostly ignore the two last lines of the disassembly because it’s just to return None — pretty interesting if you think about it. So, our first result is: Both operations take exactly the same number of opcodes (6, to be precise) to compute the same thing. bool() is getattr and call, not not is twice a unary not. Let’s go ahead.

bash:
  1. $ python -m timeit -n 10000000 "not not 5"
  2. 10000000 loops, best of 3: 0.149 usec per loop
  3. $ python -m timeit -n 10000000 "bool(5)"
  4. 10000000 loops, best of 3: 0.605 usec per loop

Oww, what’s that? Double negation is around four times faster than bool(). I’m proud to introduce the new boolean idiom to you: not not object

Artikel bearbeiten

Kommentieren

Snippet of the moment III · 1261 Tage zuvor von stargaming

python:
  1. #!/usr/bin/env python
  2. # encoding: rot13
  3.  
  4. # insert code here

Python wird dann den Quelltext direkt mit rot13 verschlüsseln/entschlüsseln (was ja bei ROT13 keinen Unterschied macht). So könnte man auf einfache — wenn auch sehr rudimentäre — Art und Weise seine Skripte verschlüsseln (vorher selbst mit ROT13 verschlüsseln und dann diese Direktive einfach oben eintragen). ;)

Artikel bearbeiten

Kommentieren

Ältere