Python のスコープについて

こんな認識であってるのかなぁ?と思ってツラツラ書いてみる

関数はスコープ持ってるのでそのまま代入しても global の値は変更されない。

In [1]: foo = 0

In [2]: def bar():
   ...:     foo = 1
   ...: 

In [3]: print foo
0

In [4]: bar()

In [5]: print foo
0

(関数内で global で宣言すればOKだけど)

In [2]: def bar():
   ...:     global foo
   ...:     foo = 1
   ...: 

でもこんな書き方は出来ない

In [12]: def bar():
   ....:     global foo = 1
------------------------------------------------------------
   File "<ipython console>", line 2
     global foo = 1
                ^
SyntaxError: invalid syntax

値が代入されて有効になる(宣言時に初期化とかされない)

In [1]: def bar():
   ...:     global j
   ...: 

In [2]: bar()

In [3]: print j
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)

/home/yoshiori/<ipython console> in <module>()

NameError: name 'j' is not defined

ブロックスコープとかは無いので for で宣言(代入)した値も for 文の外からアクセス出来る。

In [6]: for i in range(10):
   ...:     print i
   ...: 
0
1
2
3
4
5
6
7
8
9

In [7]: print i
9

同じ理屈で if 文の中で宣言(代入)した値も if 文の外からアクセス出来る。

In [8]: if True:
   ...:     hoge = 100
   ...: 

In [9]: print hoge
100

なんというか代入前に参照すると not defined じゃなく値の割り当てがされてないよ的な事を言われる

In [4]: def bar():
   ...:     print hoge
   ...:     hoge = "hoge"
   ...: 

In [5]: bar()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)

/home/yoshiori/<ipython console> in <module>()

/home/yoshiori/<ipython console> in bar()

js っぽい感じ?

わーい「清楚なクライアント」使ってくれる人が出てきた!!!

なんというか書き捨てでは無いけど別に綺麗に書こうとか思わないで書いてるソースなので
Blog に貼りつけてるだけにしたら id:a2c さんが使ってくれたり改良してくれたりしてました!!
ワーイヽ(゜∀゜)メ(゜∀゜)メ(゜∀゜)ノワーイ

PS: id:jYoshiori < codereposなどに上げてくれるとうれしいなぁ。 勝手に上げるのはさすがにマズイと自重した。

twitter & wassr クライアント決定版! かも知れない - When it’s ready.

そんな気にしないであげちゃって下さいよぉ♪
でも折角なので上げておきました><
http://coderepos.org/share/browser/lang/python/misc/tw2.py


なんか HatenaHaiku に対応してるけど消してたりするけど
気にしないでくだしあ><

wassr と Twitter への投稿クライアント(清楚なクライアント)

そういえばソース公開してなかったので……
自分用なので色々実験したりしててきちゃないコードです><


何か入力するとクロスポストして、
何も入力せずに Return で replies が表示されます。
replies にいる ID は tab 補完が出来ます。
Outputz に文字数を投稿します。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys, simplejson, urllib2, urllib, twitter as tw, readline
from pit import Pit


#source = 'profile_answer'
source = '清楚なクライアント'

class Wassr:
	def __init__(self, user, passwd):
		self.user = user
		self.passwd = passwd

	def post(self, text):
		text = text.encode('utf-8')
#		text = text.encode('utf-7')
		self.getOpener().open('http://api.wassr.jp/statuses/update.json', urllib.urlencode({'status':text,'source':source}))

	def getTimeline(self):
		url = 'http://api.wassr.jp/statuses/friends_timeline.json'
		r = self.getOpener().open(url)
		data = simplejson.loads(r.read())
		return data

	def getReplies(self):
		url = 'http://api.wassr.jp/statuses/replies.json'
		r = self.getOpener().open(url)
		data = simplejson.loads(r.read())
		return data


	def getOpener(self):
		passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
		passman.add_password(None, 'api.wassr.jp', self.user, self.passwd)
		authhandler = urllib2.HTTPBasicAuthHandler(passman)
		opener = urllib2.build_opener(authhandler)
		opener.addheaders = [('User-agent', 'WassrClient(http://d.hatena.ne.jp/jYoshiori/)')]
		return opener

class Outputz:
	def __init__(self,key,uri):
		self.key = key
		self.uri = uri

	def post(self,count):
		param = urllib.urlencode({'key':self.key,'uri':self.uri, 'size':count})
		self.getOpener().open('http://outputz.com/api/post', param)

	def getOpener(self):
		opener = urllib2.build_opener()
		opener.addheaders = [('User-agent', 'OutputsMiniblogClient(%s)' % self.uri)]
		return opener

if __name__ == "__main__":
	readline.parse_and_bind("tab: complete")
	wassr_config = Pit.get('wassr.jp',{'require' : {'user':'Your wassr name','password':'Your wassr password'}})
	wassr = Wassr(wassr_config['user'],wassr_config['password'])
	twitter_config = Pit.get('twitter.com',{'require' : {'user':'Your twitter name','password':'Your twitter password'}})
	twitter = tw.Api(twitter_config['user'], twitter_config['password'])
	friends = set()

	outputz_key = Pit.get('outputz.com',{'require' : {'key':'Your outputz key'}})['key']

	twitter_outputz = Outputz(outputz_key, 'http://twitter.com/%s' % twitter_config['user'])
	wassr_outputz = Outputz(outputz_key, 'http://wassr.jp/user/%s' % wassr_config['user'])


	def complete(text, status):
		results = [x for x in friends if x.startswith(text)] + [None]
		return results[status]

	readline.set_completer(complete)

	while True:
		input = raw_input('> ')
		input = unicode(input,'utf-8')
		if input:
			wassr.post(input)
			twitter.PostUpdate(input)
			twitter_outputz.post(len(input))
			wassr_outputz.post(len(input))

			print 'update : ' + input
		else:
			print '\twassr replies\t'
			for data in reversed(wassr.getReplies()):
				print '%-12s : %s' % (data['user_login_id'] ,data['text'])
				friends.add(data['user_login_id'])
			print '\n\ttwitter replies\t'
			for data in reversed(twitter.GetReplies()):
				print '%-12s : %s' % (data.GetUser().GetScreenName() ,data.GetText())
				friends.add(data.GetUser().GetScreenName())

コンソール出力の文字化けを無理矢理回避

コンソールのエンコードJava のシステムエンコーディングにあわせるとか色々あるんだけど
コンソールのエンコード変更とか他に影響出まくりなので
こんな関数つくって無理矢理回避した。

import sys

def p(data):
    if sys.platform.find('java') > -1:
      import java
      java.lang.System.out.write(java.lang.String(data).getBytes("utf-8"));
      print 
    else:
      print data

出るから良し

    • -

jbking 『それを高階関数で使うんですね、わかりま(ry』(2008/11/20 14:48)

こうですか?わかりません><

hoge(lambda data :(sys.platform.find('java') > -1 and ([globals().__setitem__('java',__import__('java'))] and [java.lang.System.out.write(java.lang.String(data).getBytes("utf-8"))] and [sys.stdout.write('\n')]) or [sys.stdout.write(data + '\n')])
)

関数オブジェクトについて

>>> import twitter
>>> twitter.Api()
<twitter.Api object at 0xb7d1bbec>
>>> a = _
>>> b = twitter.Api()
>>> a == b
False
>>> a.GetUser
<bound method Api.GetUser of <twitter.Api object at 0xb7d1bbec>>
>>> c = _
>>> d = b.GetUser
>>> d
<bound method Api.GetUser of <twitter.Api object at 0xb7d1be8c>>
>>> e = a.GetUser
>>> e
<bound method Api.GetUser of <twitter.Api object at 0xb7d1bbec>>
>>> c == e
True
>>> c == d
False

同じオブジェクトから取得した関数は同じ関数だけど
違うオブジェクトから取得した関数は別物みたい

>>> f = twitter.Api.GetUser
>>> f
<unbound method Api.GetUser>
>>> g = twitter.Api.GetUser
>>> g
<unbound method Api.GetUser>
>>> f == g
True

クラスメソッド自体は毎回おなじのが返ってくる。


オブジェクトが状態を持つからある意味あたりまえといえば当たり前かぁ

self について

ここにとても明快な論拠がある。"self"を明示的に引数として記述することによって,以下の2つの関数呼び出しが論理的に同じであることを補強できる,というのである。つまり,メソッドfooはクラスCのインスタンスであることを論理的に示せるわけだ。

foo.meth(arg) == C.meth(foo, arg)

和訳 なぜPythonのメソッド引数に明示的にselfと書くのか | TRIVIAL TECHNOLOGIES 4 @ats のイクメン日記

ふむふむ
書いてみる

#!/usr/bin/env python
# -*- coding: utf-8 -*-

class C:

    def __init__(self,bar):
        self.bar = bar

    def foo(self,data):
        print self.bar, data

c = C('hoge1');
c.foo('hoge1-1');

C.foo(c,'hoge1-2')

結果

hoge1 hoge1-1
hoge1 hoge1-2

なるほどなるほど

おやつ2日目

10/25 16:30 まで、予算は 1 万円くらいでお願いします。

単位を書くこと!!

2色シュークリーム 29個
ハッピーターン 3袋
甘み控えめのチョコレート 2袋
バナナ 6房
ソフトサラダ 3袋
チョコレート(板チョコ、あまり甘くないやつ) 3枚
ウーロン茶1.5L 2本
たこ焼 3パック
チョコパイ 3袋
暴君ハバネロ・悪夢のハロウィン」無ければ「ジョロキア」 4袋
Javaティー(1.5L) 2本
ポテチ塩味 2袋
ルマンド 5袋
ペプシNEX 2L 5本
プリングルス(種類問わず) 5本
ガラナ 3本
ジンジャーエールゼロ 1.5L 2本
アイスコーヒー(ブラック) 1L 5本
ダイエットコーラ 1.5L 3本
オールレーズン 4袋
ネクター(桃) 1000mL
コイケヤのり塩 3袋
うまい棒(コーンスープ味) 1うまい棒
ドリップコーヒー 30 pack
ハートチップス 3袋
ポテチ(チーズ味) 3*60g程度
ピザポテト(リベンジ) 2袋
みかん 4袋
ビーフジャーキー(天狗希望) 1kg
ジャッキーカルパス 3袋
魚肉ソーセージ(ビック) 5本

みんな変なもの頼みすぎ