文字列とか配列とかのスライスって使い易い!
辞書って使い易い!
って所から始まって、ついやりすぎてしまった。
とりあえず名前はPHPyとしておいた。
多分Strは日本語非対応。
意外と時間かかった…。
移植した型
・Tuple
・List
・Dict
・Frozenset
・Set
・Str
・Int
・Xrange
テストコード
Tuple
<?php require_once('PHPy.php'); try { echo "### PyTuple\n\n"; $tuple = new PyTuple('aaa', 'bbb', 'ccc', 'ddd', 'eee'); echo "# slice\n"; printf("'%s': %s\n", '0:3', $tuple['0:3']); printf("'%s': %s\n", '1:4', $tuple['1:4']); printf("'%s': %s\n", '-3:', $tuple['-3:']); printf("'%s': %s\n", '4', $tuple['4']); echo "\n"; echo "# toString\n"; echo $tuple."\n\n"; echo "# toArray\n"; print_r($tuple->toArray()); echo "\n"; echo "# iterator\n"; foreach ($tuple as $key=>$value) { printf("%s: %s\n", $key, $value); } } catch (PyException $e) { printf("%s: %s (Line:%d)\n", get_class($e), $e->getMessage(), $e->getLine()); } catch (Exception $e) { printf("%s: %s (Line:%d)\n", get_class($e), $e->getMessage(), $e->getLine()); }
### PyTuple # slice '0:3': ('aaa', 'bbb', 'ccc') '1:4': ('bbb', 'ccc', 'ddd') '-3:': ('ccc', 'ddd', 'eee') '4': eee # toString ('aaa', 'bbb', 'ccc', 'ddd', 'eee') # toArray Array ( [0] => aaa [1] => bbb [2] => ccc [3] => ddd [4] => eee ) # iterator 0: aaa 1: bbb 2: ccc 3: ddd 4: eee
List
<?php require_once('PHPy.php'); try { echo "### PyList\n\n"; $list = new PyList('aaa', 'bbb', 'ccc', 'ddd', 'eee'); echo "# slice\n"; printf("'%s': %s\n", '0:3', $list['0:3']); printf("'%s': %s\n", '1:4', $list['1:4']); printf("'%s': %s\n", '-3:', $list['-3:']); printf("'%s': %s\n", '4', $list['4']); echo "\n"; echo "# toString\n"; echo $list."\n\n"; echo "# toArray\n"; print_r($list->toArray()); echo "\n"; echo "# iterator\n"; foreach ($list as $key=>$value) { printf("%s: %s\n", $key, $value); } echo "\n"; echo "# append\n"; $list->append(new PyList('fff', 'ggg')); echo $list."\n\n"; echo "# extend\n"; $list->extend(new PyList('hhh', 'iii')); echo $list."\n\n"; echo "# insert\n"; $list->insert(4, 'jjj'); echo $list."\n\n"; echo "# remove\n"; $list->remove(new PyList('fff', 'ggg')); echo $list."\n\n"; echo "# pop\n"; $list->pop(); echo $list."\n\n"; echo "# index\n"; echo $list->index('ddd')."\n\n"; echo "# count\n"; echo $list->count('ccc')."\n\n"; echo "# sort\n"; echo $list->sort()."\n\n"; echo "# reverse\n"; echo $list->reverse()."\n\n"; } catch (PyException $e) { printf("%s: %s (Line:%d)\n", get_class($e), $e->getMessage(), $e->getLine()); } catch (Exception $e) { printf("%s: %s (Line:%d)\n", get_class($e), $e->getMessage(), $e->getLine()); }
### PyList # slice '0:3': ['aaa', 'bbb', 'ccc'] '1:4': ['bbb', 'ccc', 'ddd'] '-3:': ['ccc', 'ddd', 'eee'] '4': eee # toString ['aaa', 'bbb', 'ccc', 'ddd', 'eee'] # toArray Array ( [0] => aaa [1] => bbb [2] => ccc [3] => ddd [4] => eee ) # iterator 0: aaa 1: bbb 2: ccc 3: ddd 4: eee # append ['aaa', 'bbb', 'ccc', 'ddd', 'eee', ['fff', 'ggg']] # extend ['aaa', 'bbb', 'ccc', 'ddd', 'eee', ['fff', 'ggg'], 'hhh', 'iii'] # insert ['aaa', 'bbb', 'ccc', 'ddd', 'jjj', 'eee', ['fff', 'ggg'], 'hhh', 'iii'] # remove ['aaa', 'bbb', 'ccc', 'ddd', 'jjj', 'eee', 'hhh', 'iii'] # pop ['aaa', 'bbb', 'ccc', 'ddd', 'jjj', 'eee', 'hhh'] # index 3 # count 1 # sort ['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'hhh', 'jjj'] # reverse ['jjj', 'hhh', 'eee', 'ddd', 'ccc', 'bbb', 'aaa']
Dict
<?php require_once('PHPy.php'); try { echo "### PyDict\n\n"; $dict = new PyDict(array('aaa'=>'AAA', 'bbb'=>'BBB', 'ccc'=>'CCC', 'ddd'=>'DDD', 'eee'=>'EEE')); echo "# toString\n"; echo $dict."\n\n"; echo "# toArray\n"; print_r($dict->toArray()); echo "\n"; echo "# copy\n"; $dict2 = $dict->copy(); echo $dict2."\n\n"; echo "# clear\n"; $dict2->clear(); echo $dict2."\n\n"; echo "# has_key\n"; var_dump($dict->has_key('aaa')); echo "\n"; echo "# items\n"; echo $dict->items()."\n\n"; echo "# keys\n"; echo $dict->keys()."\n\n"; echo "# update\n"; $dict->update(array('xxx'=>'XXX', 'yyy'=>'YYY', 'zzz'=>'ZZZ')); echo $dict."\n\n"; echo "# fromkeys\n"; echo PyDict::fromkeys('abcdef', 'ABCDEF')."\n\n"; echo "# values\n"; echo $dict->values()."\n\n"; echo "# setdefault\n"; echo $dict->setdefault('ooo', 'OOO')."\n"; echo $dict."\n\n"; echo "# pop\n"; echo $dict->pop('aaa', 'not found')."\n"; echo $dict."\n\n"; echo "# popitem\n"; echo $dict->popitem()."\n"; echo $dict."\n\n"; echo "# iterator\n"; foreach ($dict as $key=>$value) { printf("%s: %s\n", $key, $value); } echo "\n"; echo "# iterator iteritems\n"; foreach ($dict->iteritems() as $key=>$value) { printf("%s: %s\n", $key, $value); } echo "\n"; echo "# iterator iterkeys\n"; foreach ($dict->iterkeys() as $key=>$value) { printf("%s: %s\n", $key, $value); } echo "\n"; echo "# iterator itervalues\n"; foreach ($dict->itervalues() as $key=>$value) { printf("%s: %s\n", $key, $value); } } catch (PyException $e) { printf("%s: %s (Line:%d)\n", get_class($e), $e->getMessage(), $e->getLine()); } catch (Exception $e) { printf("%s: %s (Line:%d)\n", get_class($e), $e->getMessage(), $e->getLine()); }
### PyDict # toString {'aaa': 'AAA', 'bbb': 'BBB', 'ccc': 'CCC', 'ddd': 'DDD', 'eee': 'EEE'} # toArray Array ( [aaa] => AAA [bbb] => BBB [ccc] => CCC [ddd] => DDD [eee] => EEE ) # copy {'aaa': 'AAA', 'bbb': 'BBB', 'ccc': 'CCC', 'ddd': 'DDD', 'eee': 'EEE'} # clear {} # has_key bool(true) # items [('aaa', 'AAA'), ('bbb', 'BBB'), ('ccc', 'CCC'), ('ddd', 'DDD'), ('eee', 'EEE')] # keys ['aaa', 'bbb', 'ccc', 'ddd', 'eee'] # update {'aaa': 'AAA', 'bbb': 'BBB', 'ccc': 'CCC', 'ddd': 'DDD', 'eee': 'EEE', 'xxx': 'XXX', 'yyy': 'YYY', 'zzz': 'ZZZ'} # fromkeys {'a': 'ABCDEF', 'b': 'ABCDEF', 'c': 'ABCDEF', 'd': 'ABCDEF', 'e': 'ABCDEF', 'f': 'ABCDEF'} # values ['AAA', 'BBB', 'CCC', 'DDD', 'EEE', 'XXX', 'YYY', 'ZZZ'] # setdefault OOO {'aaa': 'AAA', 'bbb': 'BBB', 'ccc': 'CCC', 'ddd': 'DDD', 'eee': 'EEE', 'xxx': 'XXX', 'yyy': 'YYY', 'zzz': 'ZZZ', 'ooo': 'OOO'} # pop AAA {'bbb': 'BBB', 'ccc': 'CCC', 'ddd': 'DDD', 'eee': 'EEE', 'xxx': 'XXX', 'yyy': 'YYY', 'zzz': 'ZZZ', 'ooo': 'OOO'} # popitem ('yyy', 'YYY') {'bbb': 'BBB', 'ccc': 'CCC', 'ddd': 'DDD', 'eee': 'EEE', 'xxx': 'XXX', 'zzz': 'ZZZ', 'ooo': 'OOO'} # iterator 0: bbb 1: ccc 2: ddd 3: eee 4: xxx 5: zzz 6: ooo # iterator iteritems bbb: BBB ccc: CCC ddd: DDD eee: EEE xxx: XXX zzz: ZZZ ooo: OOO # iterator iterkeys 0: bbb 1: ccc 2: ddd 3: eee 4: xxx 5: zzz 6: ooo # iterator itervalues 0: BBB 1: CCC 2: DDD 3: EEE 4: XXX 5: ZZZ 6: OOO
Frozenset
<?php require_once('PHPy.php'); try { echo "### PyFronzenset\n\n"; $fset = new PyFrozenset('abcdef'); echo "# toString\n"; echo $fset."\n\n"; echo "# toArray\n"; print_r($fset->toArray()); echo "\n"; echo "# iterator\n"; foreach ($fset as $key=>$value) { printf("%s: %s\n", $key, $value); } echo "\n"; echo "# issubset\n"; var_dump($fset->issubset('defghi')); echo "\n"; echo "# issuperset\n"; var_dump($fset->issuperset('defghi')); echo "\n"; echo "# union\n"; echo $fset->union('defghi')."\n\n"; echo "# intersection\n"; echo $fset->intersection('defghi')."\n\n"; echo "# difference\n"; echo $fset->difference('defghi')."\n\n"; echo "# symmetric_difference\n"; echo $fset->symmetric_difference('defghi')."\n\n"; echo "# copy\n"; echo $fset->copy()."\n\n"; } catch (PyException $e) { printf("%s: %s (Line:%d)\n", get_class($e), $e->getMessage(), $e->getLine()); } catch (Exception $e) { printf("%s: %s (Line:%d)\n", get_class($e), $e->getMessage(), $e->getLine()); }
### PyFronzenset # toString PyFrozenset(['a', 'b', 'c', 'd', 'e', 'f']) # toArray Array ( [0] => a [1] => b [2] => c [3] => d [4] => e [5] => f ) # iterator 0: a 1: b 2: c 3: d 4: e 5: f # issubset bool(false) # issuperset bool(true) # union PyFrozenset(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']) # intersection PyFrozenset(['d', 'e', 'f']) # difference PyFrozenset(['a', 'b', 'c']) # symmetric_difference PyFrozenset(['a', 'b', 'c', 'g', 'h', 'i']) # copy PyFrozenset(['a', 'b', 'c', 'd', 'e', 'f'])
Set
<?php require_once('PHPy.php'); try { echo "### PySet\n\n"; $set = new PySet('abcdef'); echo "# toString\n"; echo $set."\n\n"; echo "# toArray\n"; print_r($set->toArray()); echo "\n"; echo "# iterator\n"; foreach ($set as $key=>$value) { printf("%s: %s\n", $key, $value); } echo "\n"; echo "# issubset\n"; var_dump($set->issubset('defghi')); echo "\n"; echo "# issuperset\n"; var_dump($set->issuperset('defghi')); echo "\n"; echo "# union\n"; echo $set->union('defghi')."\n\n"; echo "# intersection\n"; echo $set->intersection('defghi')."\n\n"; echo "# difference\n"; echo $set->difference('defghi')."\n\n"; echo "# symmetric_difference\n"; echo $set->symmetric_difference('defghi')."\n\n"; echo "# copy\n"; echo $set->copy()."\n\n"; echo "# update\n"; $set->update('defghi'); echo $set."\n\n"; echo "# intersection_update\n"; $set->intersection_update('defghi'); echo $set."\n\n"; echo "# difference_update\n"; $set->difference_update('abcdef'); echo $set."\n\n"; echo "# symmetric_difference_update\n"; $set->symmetric_difference_update('defghi'); echo $set."\n\n"; echo "# add\n"; $set->add('x'); echo $set."\n\n"; echo "# remove\n"; $set->remove('d'); echo $set."\n\n"; echo "# discard\n"; $set->discard('e'); echo $set."\n\n"; echo "# pop\n"; echo $set->pop()."\n"; echo $set."\n\n"; echo "# clear\n"; $set->clear(); echo $set."\n\n"; } catch (PyException $e) { printf("%s: %s (Line:%d)\n", get_class($e), $e->getMessage(), $e->getLine()); } catch (Exception $e) { printf("%s: %s (Line:%d)\n", get_class($e), $e->getMessage(), $e->getLine()); }
### PySet # toString PySet(['a', 'b', 'c', 'd', 'e', 'f']) # toArray Array ( [0] => a [1] => b [2] => c [3] => d [4] => e [5] => f ) # iterator 0: a 1: b 2: c 3: d 4: e 5: f # issubset bool(false) # issuperset bool(true) # union PySet(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']) # intersection PySet(['d', 'e', 'f']) # difference PySet(['a', 'b', 'c']) # symmetric_difference PySet(['a', 'b', 'c', 'g', 'h', 'i']) # copy PySet(['a', 'b', 'c', 'd', 'e', 'f']) # update PySet(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']) # intersection_update PySet(['d', 'e', 'f', 'g', 'h', 'i']) # difference_update PySet(['g', 'h', 'i']) # symmetric_difference_update PySet(['d', 'e', 'f']) # add PySet(['d', 'e', 'f', 'x']) # remove PySet(['e', 'f', 'x']) # discard PySet(['f', 'x']) # pop f PySet(['x']) # clear PySet([])
Str
<?php require_once('PHPy.php'); try { echo "### PyStr\n\n"; $str = new PyStr('abcABCabcABC'); echo "# slice\n"; printf("'%s': %s\n", '0:3', $str['0:3']); printf("'%s': %s\n", '1:4', $str['1:4']); printf("'%s': %s\n", '-3:', $str['-3:']); printf("'%s': %s\n", '4', $str['4']); echo "\n"; echo "# toString\n"; echo $str."\n\n"; echo "# toArray\n"; print_r($str->toArray()); echo "\n"; echo "# iterator\n"; foreach ($str as $key=>$value) { printf("%s: %s\n", $key, $value); } echo "\n"; echo "# capitalize\n"; echo $str->capitalize()."\n\n"; echo "# center\n"; var_dump((string)$str->center(20)); echo "\n"; echo "# count\n"; echo $str->count('abc')."\n\n"; echo "# endswith\n"; var_dump($str->endswith("abc")); echo "\n"; echo "# expandtabs\n"; echo $str->expandtabs()."\n\n"; echo "# find\n"; echo $str->find('c')."\n\n"; echo "# index\n"; echo $str->index('c')."\n\n"; echo "# isalnum\n"; var_dump($str->isalnum()); echo "\n"; echo "# isalpha\n"; var_dump($str->isalpha()); echo "\n"; echo "# isdigit\n"; var_dump($str->isdigit()); echo "\n"; echo "# islower\n"; var_dump($str->islower()); echo "\n"; echo "# isspace\n"; var_dump($str->isspace()); echo "\n"; echo "# istitle\n"; var_dump($str->istitle()); echo "\n"; echo "# isupper\n"; var_dump($str->isupper()); echo "\n"; echo "# join\n"; echo $str->join(new PyList('===', '///', '---'))."\n\n"; echo "# ljust\n"; var_dump((string)$str->ljust(20)); echo "\n"; echo "# lower\n"; echo $str->lower()."\n\n"; echo "# lstrip\n"; echo $str->lstrip()."\n\n"; echo "# partition\n"; echo $str->partition('ABC')."\n\n"; echo "# replace\n"; echo $str->replace('ABC', 'OPQ')."\n\n"; echo "# rfind\n"; echo $str->rfind('ABC')."\n\n"; echo "# rindex\n"; echo $str->rfind('ABC')."\n\n"; echo "# rjust\n"; var_dump((string)$str->rjust(20)); echo "\n"; echo "# rpartition\n"; echo $str->rpartition('abc')."\n\n"; echo "# rsplit\n"; echo $str->rsplit('c')."\n\n"; echo "# rstrip\n"; echo $str->rstrip('C')."\n\n"; echo "# strip\n"; echo $str->strip('C')."\n\n"; echo "# splitlines\n"; echo $str->splitlines()."\n\n"; echo "# startswith\n"; echo $str->startswith('abc')."\n\n"; echo "# strip\n"; echo $str->strip('c')."\n\n"; echo "# swapcase\n"; echo $str->swapcase()."\n\n"; echo "# title\n"; echo $str->title()."\n\n"; echo "# upper\n"; echo $str->upper()."\n\n"; echo "# zfill\n"; echo $str->zfill(30)."\n\n"; } catch (PyException $e) { printf("%s: %s (Line:%d)\n", get_class($e), $e->getMessage(), $e->getLine()); } catch (Exception $e) { printf("%s: %s (Line:%d)\n", get_class($e), $e->getMessage(), $e->getLine()); }
### PyStr # slice '0:3': abc '1:4': bcA '-3:': ABC '4': B # toString abcABCabcABC # toArray Array ( [0] => a [1] => b [2] => c [3] => A [4] => B [5] => C [6] => a [7] => b [8] => c [9] => A [10] => B [11] => C ) # iterator 0: a 1: b 2: c 3: A 4: B 5: C 6: a 7: b 8: c 9: A 10: B 11: C # capitalize Abcabcabcabc # center string(20) " abcABCabcABC " # count 2 # endswith bool(false) # expandtabs abcABCabcABC # find 2 # index 2 # isalnum bool(true) # isalpha bool(true) # isdigit bool(false) # islower bool(false) # isspace bool(false) # istitle bool(false) # isupper bool(false) # join ===abcABCabcABC///abcABCabcABC--- # ljust string(20) "abcABCabcABC " # lower abcabcabcabc # lstrip abcABCabcABC # partition ("abc", "ABC", "abcABC") # replace abcOPQabcOPQ # rfind 9 # rindex 9 # rjust string(20) " abcABCabcABC" # rpartition ("abcABC", "abc", "ABC") # rsplit ['ab', 'ABCab', 'ABC'] # rstrip abcABCabcAB # strip abcABCabcAB # splitlines ['abcABCabcABC'] # startswith 1 # strip abcABCabcABC # swapcase ABCabcABCabc # title Abcabcabcabc # upper ABCABCABCABC # zfill 000000000000000000abcABCabcABC
Int
<?php require_once('PHPy.php'); try { echo "### PyInt\n\n"; $int = new PyInt('FFFFFFFF', 16); echo "# toString\n"; echo $int."\n\n"; echo "# abs\n"; echo $int->abs()."\n\n"; echo "# toInt\n"; echo $int->toInt()."\n\n"; echo "# pow\n"; echo $int->pow(2)."\n\n"; } catch (PyException $e) { printf("%s: %s (Line:%d)\n", get_class($e), $e->getMessage(), $e->getLine()); } catch (Exception $e) { printf("%s: %s (Line:%d)\n", get_class($e), $e->getMessage(), $e->getLine()); }
### PyInt # toString 4294967295 # abs Resource id #6 # toInt 2147483647 # pow 18446744065119617025
Xrange
<?php require_once('PHPy.php'); try { echo "### PyXrange\n\n"; $xrange = new PyXrange(10); echo "# toString\n"; echo $xrange."\n\n"; echo "# toArray\n"; print_r($xrange->toArray()); echo "\n"; echo "# iterator\n"; foreach ($xrange as $key=>$value) { printf("%s: %s\n", $key, $value); } } catch (PyException $e) { printf("%s: %s (Line:%d)\n", get_class($e), $e->getMessage(), $e->getLine()); } catch (Exception $e) { printf("%s: %s (Line:%d)\n", get_class($e), $e->getMessage(), $e->getLine()); }
### PyXrange # toString xrange(0, 10, 1) # toArray Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3 [4] => 4 [5] => 5 [6] => 6 [7] => 7 [8] => 8 [9] => 9 ) # iterator 0: 0 1: 1 2: 2 3: 3 4: 4 5: 5 6: 6 7: 7 8: 8 9: 9
Function
<?php <?php require_once('PHPy.php'); try { echo "### PyFunc\n\n"; $dict = new PyDict(array('aa'=>'AA', 'bb'=>'BB', 'cc'=>'CC')); echo "# PyTuple\n"; echo PyFunc::PyTuple($dict)."\n\n"; echo "# PyList\n"; echo PyFunc::PyList($dict)."\n\n"; echo "# PyDict\n"; echo PyFunc::PyDict(array('aA', 'bB', 'cC'))."\n"; echo PyFunc::PyDict(array('a'=>'AAA', 'b'=>'BBB', 'c'=>'CCC'))."\n"; echo PyFunc::PyDict(new PyList(new PyTuple('a', 'AAA'), new PyTuple('b', 'BBB'), new PyTuple('c', 'CCC')))."\n"; echo "\n"; echo "# PyFrozenset\n"; echo PyFunc::PyFrozenset('abcdef')."\n\n"; echo "# PySet\n"; echo PyFunc::PySet('abcdef')."\n\n"; echo "# PyStr\n"; echo PyFunc::PyStr($dict)."\n\n"; echo "# PyInt\n"; echo PyFunc::PyInt("FFFFFFFF", 16)."\n\n"; echo "# PyXrange\n"; echo PyFunc::PyXrange(0, 20, 2)."\n\n"; echo "# PyRange\n"; echo PyFunc::PyRange(0, 20, 2)."\n\n"; echo "# PyLen\n"; echo PyFunc::PyLen(new PyTuple('aaa', 'bbb', 'ccc'))."\n\n"; echo "# PyAnd\n"; var_dump(PyFunc::PyAnd(1, 2, 3, 0, 4, 5)); var_dump(PyFunc::PyAnd('a', 'b', 'c', '', 'd')); var_dump(PyFunc::PyAnd(array('a', 'b'), array(), array('c'))); var_dump(PyFunc::PyAnd('a', 'b', 'c')); echo "\n"; echo "# PyOr\n"; var_dump(PyFunc::PyOr(0, 1, 2, 3)); var_dump(PyFunc::PyOr('', 'a', 'b', 'c')); var_dump(PyFunc::PyOr(array(), array('a', 'b'), array('c'))); var_dump(PyFunc::PyOr(null, 'a', 'b', 'c')); echo "\n\n"; } catch (PyException $e) { printf("%s: %s (Line:%d)\n", get_class($e), $e->getMessage(), $e->getLine()); } catch (Exception $e) { printf("%s: %s (Line:%d)\n", get_class($e), $e->getMessage(), $e->getLine()); }
### PyFunc # PyTuple ('aa', 'bb', 'cc') # PyList ['aa', 'bb', 'cc'] # PyDict {'a': 'A', 'b': 'B', 'c': 'C'} {'a': 'AAA', 'b': 'BBB', 'c': 'CCC'} {'a': 'AAA', 'b': 'BBB', 'c': 'CCC'} # PyFrozenset PyFrozenset(['a', 'b', 'c', 'd', 'e', 'f']) # PySet PySet(['a', 'b', 'c', 'd', 'e', 'f']) # PyStr {'aa': 'AA', 'bb': 'BB', 'cc': 'CC'} # PyInt 4294967295 # PyXrange xrange(0, 20, 2) # PyRange [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] # PyLen 3 # PyAnd int(0) string(0) "" array(0) { } string(1) "c" # PyOr int(1) string(1) "a" array(2) { [0]=> string(1) "a" [1]=> string(1) "b" } string(1) "a"
Other
<?php require_once('PHPy.php'); try { echo "### Other test\n\n"; echo "# setdefault\n"; $d = new PyDict(); $d->setdefault('k1', new PyList())->append('aaa'); echo $d."\n"; /* $d->setdefault('k2', new PyDict())['d1'] = 'bbb'; // Parse error: syntax error, unexpected '[' echo $d."\n"; */ $d->setdefault('k2', new PyDict())->offsetSet('d1', 'bbb'); echo $d."\n\n"; } catch (PyException $e) { printf("%s: %s (Line:%d)\n", get_class($e), $e->getMessage(), $e->getLine()); } catch (Exception $e) { printf("%s: %s (Line:%d)\n", get_class($e), $e->getMessage(), $e->getLine()); }
### Other test # setdefault {'k1': ['aaa']} {'k1': ['aaa'], 'k2': {'d1': 'bbb'}}
PHPy.php
<?php /* Exception */ class PyException extends Exception{} class PyTypeError extends PyException{} class PyValueError extends PyException{} class PyIndexError extends PyException{} class PyAttributeError extends PyException{} class PyKeyError extends PyException{} /* Function */ class PyFunc { // Cast function public static function PyTuple($data=array()) { $data = PyUtils::toArray($data); $obj = new PyTuple(); call_user_func_array(array($obj, '__construct'), $data); return $obj; } public static function PyList($data=array()) { $data = PyUtils::toArray($data); $obj = new PyList(); call_user_func_array(array($obj, '__construct'), $data); return $obj; } public static function PyDict($data=array()) { return new PyDict($data); } public static function PyFrozenset($data=array()) { return new PyFrozenset($data); } public static function PySet($data=array()) { return new PySet($data); } public static function PyStr($obj='') { return new PyStr($obj); } public static function PyInt($num=0, $base=10) { return new PyInt($num, $base); } public static function PyXrange() { $args = func_get_args(); $obj = new PyXrange(1); call_user_func_array(array($obj, '__construct'), $args); return $obj; } // Python function public static function PyRange() { $args = func_get_args(); switch (func_num_args()) { case 1: $args = array(0, $args[0], 1); break; case 2: $args = array($args[0], $args[1], 1); break; case 3: $args = array($args[0], $args[1], $args[2]); break; default: throw new PyTypeError(sprintf('range expected at least 1 arguments, got %d', func_num_args())); break; } foreach ($args as $arg) { if (strcmp((string)(int)$arg, (string)$arg)!=0) { throw new PyTypeError('range() integer end argument expected, got str.'); } } $range = array(); if (0<$args[2]) { for ($i=$args[0]; $i<$args[1]; $i+=$args[2]) { $range[] = $i; } } elseif ($args[2]<0) { for ($i=$args[0]; $args[1]<$i; $i+=$args[2]) { $range[] = $i; } } else { throw new PyValueError('range() step argument must not be zero'); } $obj = new PyList(); call_user_func_array(array($obj, '__construct'), $range); return $obj; } public static function PyLen($obj) { return PyUtils::getLength($obj); } // Operator function public static function PyAnd() { $args = func_get_args(); $obj = null; foreach ($args as $obj) { if (!PyUtils::toBool($obj)) { return $obj; } } return $obj; } public static function PyOr() { $args = func_get_args(); $obj = null; foreach ($args as $obj) { if (PyUtils::toBool($obj)) { return $obj; } } return $obj; } } /* Utils */ class PyUtils { public static function sliceNormalize($datalen, $slice) { $slice = str_replace(' ', '', $slice); if (!preg_match('/^(\-?[0-9]+)?(:(\-?[0-9]+)?)?$/', $slice) || strlen($slice)==0) { throw new PyTypeError('slice indices must be integers'); } $muluti = false; $slice = explode(':', $slice); $start = (int)$slice[0]; $end = $start+1; // muluti if (count($slice)==2) { $muluti = true; $end = $datalen; if (0<strlen($slice[1])) { $end = (int)$slice[1]; } } // minuse if ($start<0) { $start = max(0, $start+$datalen); } if ($end<0) { $end = max(0, $end+$datalen); } // len over $start = min($datalen, $start); $end = min($datalen, $end); return array($start, $end, $muluti); } /* Cast */ public static function toArray($obj) { if ($obj instanceof PyDict) { $obj = array_keys($obj->toArray()); } elseif ($obj instanceof PyObject) { $obj = $obj->toArray(); } if (!is_array($obj) && !is_string($obj)) { throw new PyTypeError(sprintf("'%s' object is not iterable", gettype($obj))); } if (!is_array($obj)) { $obj = str_split((string)$obj); } return $obj; } public static function toAssoc($obj) { $arr = PyUtils::toArray($obj); if ($obj instanceof PyObject) { $obj = $obj->toArray(); } // assoc if (is_array($obj)) { foreach ($obj as $k=>$v) { if (!is_int($k)) { return $obj; } } } // array $result = array(); foreach ($arr as $i=>$item) { $item = PyUtils::toPureObject($item); try { $len = PyUtils::getLength($item); if ($len!=2) { throw new PyValueError(sprintf('dictionary update sequence element #%d has length %d; 2 is required', $i, $len)); } $result[PyUtils::toString($item[0])] = $item[1]; } catch (PyTypeError $e) { throw new PyTypeError(sprintf('cannot convert dictionary update sequence element #%d to a sequence', $i)); } catch (PyValueError $e) { throw $e; } } return $result; } public static function toString($obj) { return (string)$obj; } public static function toBool($obj) { if ($obj instanceof PyObject) { $obj = $obj->toPureObject(); } if (is_string($obj)) { return 0<strlen($obj); } return (bool)$obj; } public static function toDump($data, $preSymbol, $sufSymbol, $key_flag, $comma_flag) { $result = array(); foreach ($data as $key=>$item) { $key = $key_flag ? sprintf("'%s': ", $key) : ''; // PyObject if ($item instanceof PyObject) { $result[] = $key . $item->toDump(); // string } elseif (is_string($item)) { $item = str_replace('\\', '\\\\', $item); $item = str_replace("'", "\\'", $item); $result[] = $key . sprintf("'%s'", $item); // other } else { $result[] = $key . json_encode($item); } } $comma = ''; if (count($result)<=1 && $comma_flag) { $comma = ','; } return $preSymbol . implode(', ', $result) . $comma . $sufSymbol; } public static function getLength($obj) { $obj = PyUtils::toPureObject($obj); if (is_string($obj)) { return strlen($obj); } elseif (is_array($obj)) { return count($obj); } throw new PyTypeError(sprintf("object of type '%s' has no len()", gettype($obj))); } public static function toPureObject($obj) { if ($obj instanceof PyObject) { $obj = $obj->toPureObject(); } return $obj; } public static function toPureObjectAll($obj) { if ($obj instanceof PyObject) { $obj = $obj->toPureObject(); } $result = $obj; if (is_array($obj)) { $result = array(); foreach ($obj as $key=>$value) { $result[$key] = PyUtils::toPureObjectAll($value); } } return $result; } } /* Class */ // Object abstract class PyObject implements ArrayAccess { public function __toString() { return $this->toString(); } public function toArray() { throw new PyTypeError(sprintf("'%s' object is not iterable", get_class($this))); } abstract public function toString(); abstract public function toDump(); abstract public function toPureObject(); /* ArrayAccess */ public function offsetExists($offset) { try { $this->offsetGet($offset); return true; } catch(Exception $e) { return false; } } public function offsetUnset($index) { throw new PyTypeError(sprintf("'%s' object doesn't support item deletion", get_class($this))); } public function offsetGet($index) { throw new PyTypeError(sprintf("'%s' object doesn't support item deletion", get_class($this))); } public function offsetSet($index, $value) { throw new PyTypeError(sprintf("'%s' object does not support item assignment", get_class($this))); } } abstract class PyIteratorAggregate extends PyObject implements IteratorAggregate { /* IteratorAggregate */ public function getIterator() { if ($this instanceof PyDict) { return $this->iterkeys(); } return new ArrayIterator($this->toArray()); } } abstract class PyIterator extends PyObject implements Iterator { } // Tuple class PyTuple extends PyIteratorAggregate { protected $_data = array(); public function __construct() { $this->_data = func_get_args(); } /* Extend method */ // ArrayAccess public function offsetSet($index, $data) { throw new PyTypeError(sprintf("'%s' object does not support item assignment", get_class($this))); } public function offsetGet($index) { list($index_start, $index_end, $muluti) = PyUtils::sliceNormalize(count($this->_data), $index); // obj if ($muluti) { $result = array(); for ($i=$index_start; $i<$index_end; $i++) { if ($i<count($this->_data)) { $result[] = $this->_data[$i]; } } // instance $classname = get_class($this); $obj = new $classname(); call_user_func_array(array($obj, '__construct'), $result); return $obj; // not obj } else { if (count($this->_data)<=$index_start) { throw new PyIndexError('list index out of range'); } return $this->_data[$index_start]; } } // Cast public function toArray() { return $this->_data; } public function toString() { return $this->toDump(); } public function toDump() { return PyUtils::toDump($this->_data, '(', ')', false, true); } public function toPureObject() { return $this->toArray(); } } // List class PyList extends PyTuple { protected $_data = array(); /* Python method */ public function append($x) { array_push($this->_data, $x); return $this; } public function extend($L) { if ($L instanceof PyObject) { $L = $L->toArray(); } if (!is_array($L)) { $L = array($L); } foreach ($L as $x) { $this->append($x); } return $this; } public function insert($i, $item) { if (!is_int($i)) { throw new PyTypeError('an integer is required'); } while ($i<0) { $i += count($this->_data); } $tmp = array(); $insert = false; foreach ($this->_data as $key=>$value) { if ($i==$key) { $tmp[] = $item; $insert = true; } $tmp[] = $value; } if ($insert==false) { $tmp[] = $item; } $this->_data = $tmp; return $this; } public function remove($item) { $key = array_search($item, $this->_data); if ($key===false) { throw new PyValueError('list.remove(x): x not in list'); } unset($this->_data[$key]); $this->_data = array_values($this->_data); return $this; } public function pop($i=-1) { if (!is_int($i)) { throw new PyTypeError('an integer is required'); } while ($i<0) { $i += count($this->_data); } if (count($this->_data)<=$i) { throw new PyIndexError('pop index out of range'); } $pop = $this->_data[$i]; unset($this->_data[$i]); $this->_data = array_values($this->_data); return $pop; } public function index($x) { $key = array_search($x, $this->_data); if ($key==false) { throw new PyValueError('list.index(x): x not in list'); } return $key; } public function count($x) { $c = 0; foreach ($this->_data as $item) { if ($x===$item) { $c++; } } return $c; } public function sort() { sort($this->_data); $tmp = array(); // object foreach ($this->_data as $item) { if (!is_scalar($item)) { $tmp[] = $item; } } // scalar foreach ($this->_data as $item) { if (is_scalar($item)) { $tmp[] = $item; } } $this->_data = $tmp; return $this; } public function reverse() { rsort($this->_data); $tmp = array(); // scalar foreach ($this->_data as $item) { if (is_scalar($item)) { $tmp[] = $item; } } // object foreach ($this->_data as $item) { if (!is_scalar($item)) { $tmp[] = $item; } } $this->_data = $tmp; return $this; } /* Extend method */ // ArrayAccess public function offsetSet($index, $data) { list($index_start, $index_end, $muluti) = PyUtils::sliceNormalize(count($this->_data), $index); // obj if ($muluti) { // pop for ($i=$index_start; $i<$index_end; $i++) { if ($index_start<count($this->_data)) { $this->pop($index_start); } } // insert $data = PyUtils::toArray($data); foreach ($data as $key=>$value) { $this->insert($index_start+$key, $value); } // not obj } else { if (count($this->_data)<=$index_start) { throw new PyIndexError('list assignment index out of range'); } $this->_data[$index_start] = $data; } } // Cast public function toDump() { return PyUtils::toDump($this->_data, '[', ']', false, false); } } // Dict class PyDict extends PyIteratorAggregate { protected $_data = array(); public function __construct($arr=array()) { $this->update($arr); } /* Python method */ public function clear() { $this->_data = array(); } public function copy() { return clone $this; } public function has_key($k) { try { $this[$k]; } catch (PyKeyError $e) { return false; } return true; } public function items() { $obj = new PyList(); foreach ($this->_data as $key=> $value) { $obj->append(new PyTuple($key, $value)); } return $obj; } public function keys() { $keys = array_keys($this->_data); $obj = new PyList(); call_user_func_array(array($obj, '__construct'), $keys); return $obj; } public function update($dict) { $dict = PyUtils::toAssoc($dict); $this->_data = array_merge($this->_data, $dict); } public static function fromkeys($seq, $value=null) { $seq = PyUtils::toArray($seq); $obj = new PyDict(); foreach ($seq as $key) { $obj[$key] = $value; } return $obj; } public function values() { $values = array_values($this->_data); $obj = new PyList(); call_user_func_array(array($obj, '__construct'), $values); return $obj; } public function get($k, $x=null) { try { $v = $this[$k]; return $v; } catch (PyKeyError $e) { return $x; } } public function setdefault($k ,$x=null) { try { return $this[$k]; } catch (PyKeyError $e) { $this[$k] = $x; return $this[$k]; } } public function pop($k, $x=null) { try { $v = $this[$k]; unset($this->_data[$k]); return $v; } catch (PyKeyError $e) { return $x; } } public function popitem() { if (count($this->_data)==0) { throw new PyKeyError("'popitem(): dictionary is empty'"); } $key = array_rand($this->_data); $value = $this->_data[$key]; unset($this->_data[$key]); return new PyTuple($key, $value); } public function iteritems() { return new ArrayIterator($this->toArray()); } public function iterkeys() { return new ArrayIterator(array_keys($this->toArray())); } public function itervalues() { return new ArrayIterator(array_values($this->toArray())); } /* Extend method */ // ArrayAccess public function offsetGet($key) { if (!array_key_exists($key, $this->_data)) { throw new PyKeyError(sprintf("'%s'", $key)); } return $this->_data[$key]; } public function offsetSet($key, $value) { $this->_data[$key] = $value; } // Cast public function toArray() { return $this->_data; } public function toString() { return $this->toDump(); } public function toDump() { return PyUtils::toDump($this->_data, '{', '}', true, false); } public function toPureObject() { return $this->toArray(); } } // Frozenset class PyFrozenset extends PyIteratorAggregate { protected $_data = array(); public function __construct($data=array()) { $data = PyUtils::toArray($data); $data = array_unique($data); $this->_data = array_values($data); } /* Python method*/ public function issubset($t) { $t = PyUtils::toArray($t); foreach ($t as $item) { if (array_search($item, $this->_data)===false) { return false; } } return true; } public function issuperset($t) { $t = PyUtils::toArray($t); foreach ($this->_data as $item) { if (array_search($item, $this->_data)===false) { return false; } } return true; } public function union($t) { $t = PyUtils::toArray($t); $union = array_merge($this->_data, $t); $classname = get_class($this); return new $classname($union); } public function intersection($t) { $t = PyUtils::toArray($t); $inter = array_intersect($this->_data, $t); $classname = get_class($this); return new $classname($inter); } public function difference($t) { $t = PyUtils::toArray($t); $diff = array_diff($this->_data, $t); $classname = get_class($this); return new $classname($diff); } public function symmetric_difference($t) { $t = PyUtils::toArray($t); $diff1 = array_diff($this->_data, $t); $diff2 = array_diff($t, $this->_data); $diff = array_merge($diff1, $diff2); $classname = get_class($this); return new $classname($diff); } public function copy() { return clone $this; } /* Extend method */ // Cast public function toArray() { return $this->_data; } public function toString() { return $this->toDump(); } public function toDump() { $classname = get_class($this); return PyUtils::toDump($this->_data, $classname.'([', '])', false, false); } public function toPureObject() { return $this->toArray(); } } // Set class PySet extends PyFrozenset { /* Python method */ public function update($t) { $t = PyUtils::toArray($t); $union = array_merge($this->_data, $t); $this->_data = array_unique($union); } public function intersection_update($t) { $t = PyUtils::toArray($t); $inter = array_intersect($this->_data, $t); $this->_data = array_unique($inter); } public function difference_update($t) { $t = PyUtils::toArray($t); $diff = array_diff($this->_data, $t); $this->_data = array_unique($diff); } public function symmetric_difference_update($t) { $t = PyUtils::toArray($t); $diff1 = array_diff($this->_data, $t); $diff2 = array_diff($t, $this->_data); $diff = array_merge($diff1, $diff2); $this->_data = array_unique($diff); } public function add($x) { $this->update(array($x)); } public function remove($x) { $key = array_search($x, $this->_data); if ($key===false) { throw new PyKeyError(sprintf("'%s'", $x)); } unset($this->_data[$key]); } public function discard($x) { try { $this->remove($x); } catch (PyKeyError $e) { } } public function pop() { if (count($this->_data)==0) { throw new PyKyError("'pop from an empty set'"); } return array_shift($this->_data); } public function clear() { $this->_data = array(); } } // Str class PyStr extends PyIteratorAggregate { protected $_data = ''; public function __construct($s='') { $num = func_num_args(); if (1<$num) { throw new PyTypeError(sprintf("PyStr() takes at most 1 argument (%d given)", $num)); } $this->_data = (string)$s; } /* Python method */ public function capitalize() { return new PyStr(ucfirst(strtolower($this->_data))); } public function center($width, $fillchar=' ') { $fillchar = PyUtils::toString($fillchar); if (strlen($fillchar)!=1) { throw new PyTypeError('center() argument 2 must be char, not str'); } $len = $width - strlen($this->_data); if ($len<=0) { return $this->_data; } $l_len = ceil($len/2); $r_len = floor($len/2); return new PyStr(str_repeat($fillchar, $l_len) . $this->_data . str_repeat($fillchar, $r_len)); } public function count($sub, $start='', $end='') { $str = (string)$this[sprintf('%s:%s', $start, $end)]; return substr_count($str, $sub); } public function endswith($suffix, $start='', $end='') { if ($suffix=='') { return true; } $str = $this[sprintf('%s:%s', $start, $end)][sprintf('-%s:', strlen($suffix))]; return $suffix==$str; } public function expandtabs($tabsize=8) { $chars = $this->_data; if (!is_int($tabsize)) { throw new Exception('an integer is required'); } $eol_index = -1; for ($i=0; $i<strlen($chars); $i++) { if (in_array($chars[$i], array("\r", "\n"))) { $eol_index = $i; } elseif ($chars[$i]=="\t") { $pre_chars = substr($chars, 0, $i); $suf_chars = substr($chars, $i+1); $space_len = ($tabsize-($i-$eol_index-1)) % $tabsize; while ($space_len<=0) { $space_len += $tabsize; } $space = str_repeat(' ', $space_len); $chars = $pre_chars.$space.$suf_chars; } } return new PyStr($chars); } public function find($sub, $start='', $end='') { list($start, $end) = PyUtils::sliceNormalize(strlen($this->_data), sprintf('%s:%s', $start, $end)); $str = $this[sprintf('%s:%s', $start, $end)]; $index = strpos($str, $sub); if ($index!==false) { return $start+$index; } return -1; } public function index($sub, $start='', $end='') { $index = $this->find($sub, $start, $end); if (-1==$index) { throw new PyValueError('substring not found'); } return $index; } public function isalnum() { return ctype_alnum($this->_data); } public function isalpha() { return ctype_alpha($this->_data); } public function isdigit() { return ctype_digit($this->_data); } public function islower() { return ctype_lower($this->_data); } public function isspace() { return ctype_space($this->_data); } public function istitle() { return 0<strlen($this->_data) && $this->title()==$this->_data; } public function isupper() { return ctype_upper($this->_data); } public function join($seq) { $seq = PyUtils::toArray($seq); return new PyStr(implode($this->_data, $seq)); } public function ljust($width, $fillchar=' ') { if ($width instanceof PyInt) { $width = $width->toInt(); } if (!is_int($width)) { throw new PyTypeError('an integer is required'); } if (strlen($fillchar)!=1) { throw new PyTypeError('ljust() argument 2 must be char, not str'); } $data = $this->_data; $filllen = $width - strlen($data); if (0<$filllen) { $data .= str_repeat($fillchar, $filllen); } return new PyStr($data); } public function lower() { return new PyStr(strtolower($this->_data)); } public function lstrip($chars=null) { if (!is_null($chars)) { return ltrim($this->_data, $chars); } return new PyStr(ltrim($this->_data)); } public function partition($sep) { $sep = (string)$sep; $index = strpos($this->_data, $sep); if ($index!==false) { $ret1 = substr($this->_data, 0, $index); $ret2 = substr($this->_data, $index, strlen($sep)); $ret3 = substr($this->_data, $index + strlen($sep)); } else { $ret1 = $this->_data; $ret2 = ''; $ret3 = ''; } return new PyTuple(new PyStr($ret1), new PyStr($ret2), new PyStr($ret3)); } public function replace($old, $new, $count=-1) { $old = (string)$old; $new = (string)$new; if (!is_int($count)) { throw new PyTypeError('an integer is required'); } $result = $this->_data; if ($count<0) { $result = str_replace($old, $new, $result); } else { $offset = -1; $oldlen = strlen($old); $pluslen = strlen($new) - $oldlen; for ($i=0; $i<$count; $i++) { $index = $offset + 1; if (0<$oldlen) { $index = strpos($result, $old, max(0, $offset)); } if ($index===false || strlen($result)<$index) { break; } $result = substr($result, 0, $index) . $new . substr($result, $index + $oldlen); $offset = max(0, $index + $pluslen); } } return new PyStr($result); } public function rfind($sub, $start='', $end='') { list($start, $end) = PyUtils::sliceNormalize(strlen($this->_data), sprintf('%s:%s', $start, $end)); $str = $this[sprintf('%s:%s', $start, $end)]; $index = strrpos($str, $sub); if ($index!==false) { return $start+$index; } return -1; } public function rindex($sub, $start='', $end='') { $index = $this->rfind($sub, $start, $end); if (-1==$index) { throw new PyValueError('substring not found'); } return $index; } public function rjust($width, $fillchar=' ') { if ($width instanceof PyInt) { $width = $width->toInt(); } if (!is_int($width)) { throw new PyTypeError('an integer is required'); } if (strlen($fillchar)!=1) { throw new PyTypeError('rjust() argument 2 must be char, not str'); } $data = $this->_data; $filllen = $width - strlen($data); if (0<$filllen) { $data = str_repeat($fillchar, $filllen) . $data; } return new PyStr($data); } public function rpartition($sep) { $sep = (string)$sep; $index = strrpos($this->_data, $sep); if ($index!==false) { $ret1 = substr($this->_data, 0, $index); $ret2 = substr($this->_data, $index, strlen($sep)); $ret3 = substr($this->_data, $index + strlen($sep)); } else { $ret1 = ''; $ret2 = ''; $ret3 = $this->_data; } return new PyTuple(new PyStr($ret1), new PyStr($ret2), new PyStr($ret3)); } public function rsplit($sep=' ', $maxsplit=-1) { $sep = (string)$sep; if (strlen($sep)==0) { throw new PyValueError('empty separator'); } $arr = explode($sep, $this->_data); if (-1<$maxsplit) { $joincount = count($arr) - $maxsplit; for ($i=0; $i<$joincount; $i++) { $arr[0] .= $sep . $arr[1]; unset($arr[1]); $arr = array_values($arr); } } $obj = new PyList(); call_user_func_array(array($obj, '__construct'), $arr); return $obj; } public function rstrip($chars=null) { if (!is_null($chars)) { return rtrim($this->_data, $chars); } return rtrim($this->_data); } public function split($sep=' ', $maxsplit=-1) { $sep = (string)$sep; if (strlen($sep)==0) { throw new PyValueError('empty separator'); } if (-1<$maxsplit) { $arr = explode($sep, $this->_data, $maxsplit); } else { $arr = explode($sep, $this->_data); } $obj = new PyList(); call_user_func_array(array($obj, '__construct'), $arr); return $obj; } public function splitlines($keepends=false) { $data = $this->_data; $arr = array(); if ($keepends) { while (strlen($data) && preg_match("/^[^\r\n]*(\r\n|\r|\n|$)/s", $data, $match)) { $match = $match[0]; $data = substr($data, strlen($match)); $arr[] = $match; } } else { $data = str_replace("\r\n", "\n", $data); $data = str_replace("\r", "\n", $data); $arr = explode("\n", $data); } $obj = new PyList(); call_user_func_array(array($obj, '__construct'), $arr); return $obj; } public function startswith($prefix, $start='', $end='') { if ($prefix=='') { return true; } $str = $this[sprintf('%s:%s', $start, $end)][sprintf(':%s', strlen($prefix))]; return $prefix==$str; } public function strip($chars=null) { if (!is_null($chars)) { return trim($this->_data, $chars); } return new PyStr(trim($this->_data)); } public function swapcase() { $arr = $this->toArray(); foreach ($arr as &$char) { if (preg_match('/[a-z]/', $char)) { $char = strtoupper($char); } elseif (preg_match('/[A-Z]/', $char)) { $char = strtolower($char); } } return new PyStr(implode('', $arr)); } public function title() { return new PyStr(ucwords(strtolower($this->_data))); } public function translate($table, $deletechars=null) { // todo } public function upper() { return new PyStr(strtoupper($this->_data)); } public function zfill($width) { return $this->rjust($width, '0'); } /* Extend method */ // ArrayAccess public function offsetGet($index) { list($index_start, $index_end, $muluti) = PyUtils::sliceNormalize(strlen($this->_data), $index); // obj if ($muluti) { if ($index_end<$index_start) { return new PyStr(''); } return new PyStr(substr($this->_data, $index_start, $index_end-$index_start)); // not obj } else { if (strlen($this->_data)<=$index_start) { throw new PyIndexError('string index out of range'); } return substr($this->_data, $index_start, 1); } } // Cast public function toArray() { return PyUtils::toArray($this->_data); } public function toString() { return $this->_data; } public function toDump() { $item = str_replace('\\', '\\\\', $this->_data); $item = str_replace('"', '\\"', $item); return sprintf('"%s"', $item); } public function toPureObject() { return $this->toString(); } } // Int class PyInt extends PyIteratorAggregate { protected $_res; public function __construct($num, $base=10) { $numorg = $num = PyUtils::toString($num); if (!ctype_digit((string)$base)) { throw new PyTypeError('an integer is required'); } $base = (int)$base; // base if ($base==0) { if (substr($num, 0, 2)=='0x') { $num = '0' . substr($num, 2); $base = '16'; } elseif (substr($num, 0, 1)=='0') { $base = 8; } else { $base = 10; } } // base over if ($base<2 || 36<$base) { throw new PyValueType('int() base must be >= 2 and <= 36'); } // num $chars = '0123456789abcdefghijklmnopqrstuvwxyz'; $chars = substr($chars, 0, $base); if (!preg_match(sprintf('/^[%s]+$/i', $chars), $num)) { throw new PyValueError(sprintf("invalid literal for int() with base %d: '%s'", $base, $numorg)); } $this->_res = gmp_init($num, $base); } public function abs() { return gmp_abs($this->_res); } public function toInt() { return gmp_intval($this->_res); } public function pow($y) { if (strcmp((string)(int)$y, (string)$y)!=0) { throw new PyTypeError("unsupported operand type(s) for ** or pow(): 'int' and 'str'"); } return gmp_strval(gmp_pow($this->_res, $y)); } /* Extend method */ // Cast public function toString() { return gmp_strval($this->_res); } public function toDump() { return $this->toString(); } public function toPureObject() { return $this->toString(); } } // Xrange class PyXrange extends PyIterator { protected $_pos; protected $_start; protected $_end; protected $_step; public function __construct() { $args = func_get_args(); switch (func_num_args()) { case 1: $args = array(0, $args[0], 1); break; case 2: $args = array($args[0], $args[1], 1); break; case 3: $args = array($args[0], $args[1], $args[2]); break; default: throw new PyTypeError('xrange() requires 1-3 int arguments'); break; } foreach ($args as $arg) { if (strcmp((string)(int)$arg, (string)$arg)!=0) { throw new PyTypeError('an integer is required'); } } if ($args[2]==0) { throw new PyValueError('xrange() arg 3 must not be zero'); } $this->_pos = 0; $this->_start = (int)$args[0]; $this->_end = (int)$args[1]; $this->_step = (int)$args[2]; } /* Extend method */ // Iterator public function rewind() { $this->_pos = 0; } public function current() { return $this->_start + $this->_step * $this->_pos; } public function key() { return $this->_pos; } public function next() { if (!$this->valid()) { throw new PyStopIteration(); } $this->_pos++; } public function valid() { $current = $this->current(); if ($this->_step<0) { return $this->_end<$current && $current<=$this->_start; } return $this->_start<=$current && $current<$this->_end; } // Cast public function toArray() { return PyFunc::PyRange($this->_start, $this->_end, $this->_step)->toArray(); } public function toString() { return sprintf('xrange(%d, %d, %d)', $this->_start, $this->_end, $this->_step); } public function toDump() { return $this->toString(); } public function toPureObject() { return $this->toArray(); } }