Showing preview only (216K chars total). Download the full file or copy to clipboard to get everything.
Repository: wklken/stackoverflow-py-top-qa
Branch: master
Commit: c1b8f1633f3b
Files: 17
Total size: 163.1 KB
Directory structure:
gitextract_lw7pi0h1/
├── README.md
└── contents/
├── qa-built-in.md
├── qa-control-flow.md
├── qa-datetime.md
├── qa-dict.md
├── qa-exception.md
├── qa-file.md
├── qa-func.md
├── qa-list.md
├── qa-math.md
├── qa-modules.md
├── qa-oop.md
├── qa-others.md
├── qa-pip-easy_install.md
├── qa-std-modules.md
├── qa-string.md
└── qa-tuple.md
================================================
FILE CONTENTS
================================================
================================================
FILE: README.md
================================================
stackoverflow-py-top-qa
=======================
Notice:
目前进度90%, 剩余40+个问题实在没时间翻了, 有兴趣的同学可以试试, 提pr. or后续我找时间处理完整.
-------------
stackoverflow上Python相关回答整理翻译(相对来说都比较简单/散,非系统学习用途,个人整理而已)
当前进度: 90%
问题个数: 135
最后更新: 2014-10-04
查看了下前面(vote前15页,挑了下,vote都是100+的样子,大概200个)的问题,[链接](http://stackoverflow.com/questions/tagged/python?page=1&sort=votes&pagesize=15)
第一页的前几个比较长,目测都有中文翻译版本,大家可以网上搜下
如果有兴趣,可以一起翻译
注意,合并了每个问题的多个答案,但是时间仓促,疏漏难免,感兴趣问题直接点链接看原文吧
### 目录
> 基础
* [基本语法控制流相关](https://github.com/wklken/stackoverflow-py-top-qa/blob/master/contents/qa-control-flow.md)
* [字符串相关](https://github.com/wklken/stackoverflow-py-top-qa/blob/master/contents/qa-string.md)
* [文件相关](https://github.com/wklken/stackoverflow-py-top-qa/blob/master/contents/qa-file.md)
* [数学相关](https://github.com/wklken/stackoverflow-py-top-qa/blob/master/contents/qa-math.md)
> 基本数据结构
* [列表](https://github.com/wklken/stackoverflow-py-top-qa/blob/master/contents/qa-list.md)
* [元组](https://github.com/wklken/stackoverflow-py-top-qa/blob/master/contents/qa-tuple.md)
* [字典](https://github.com/wklken/stackoverflow-py-top-qa/blob/master/contents/qa-dict.md)
> 进阶
* [函数](https://github.com/wklken/stackoverflow-py-top-qa/blob/master/contents/qa-func.md)
* [内置函数](https://github.com/wklken/stackoverflow-py-top-qa/blob/master/contents/qa-built-in.md)
* [异常](https://github.com/wklken/stackoverflow-py-top-qa/blob/master/contents/qa-exception.md)
* [模块](https://github.com/wklken/stackoverflow-py-top-qa/blob/master/contents/qa-modules.md)
* [标准库](https://github.com/wklken/stackoverflow-py-top-qa/blob/master/contents/qa-std-modules.md)
* [日期](https://github.com/wklken/stackoverflow-py-top-qa/blob/master/contents/qa-datetime.md)
* [oop](https://github.com/wklken/stackoverflow-py-top-qa/blob/master/contents/qa-oop.md)
> 其他
* [pip/easy_install](https://github.com/wklken/stackoverflow-py-top-qa/blob/master/contents/qa-pip-easy_install.md)
* [其他](https://github.com/wklken/stackoverflow-py-top-qa/blob/master/contents/qa-others.md)
### 待翻译问题链接(还剩0问题)
qa-tuple.md:问题 (http://stackoverflow.com/questions/2970608/what-are-named-tuples-in-python)
### 已翻译问题链接(去重)
qa-built-in.md:问题 (http://stackoverflow.com/questions/230751/how-to-flush-output-of-python-print)
qa-built-in.md:问题 (http://stackoverflow.com/questions/1835018/python-check-if-an-object-is-a-list-or-tuple-but-not-string)
qa-built-in.md:问题 (http://stackoverflow.com/questions/152580/whats-the-canonical-way-to-check-for-type-in-python)
qa-built-in.md:问题 (http://stackoverflow.com/questions/402504/how-to-determine-the-variable-type-in-python)
qa-built-in.md:问题 (http://stackoverflow.com/questions/675442/comment-out-a-python-code-block)
qa-built-in.md:问题 (http://stackoverflow.com/questions/397148/why-doesnt-python-have-multiline-comments)
qa-built-in.md:问题 (http://stackoverflow.com/questions/56011/single-quotes-vs-double-quotes-in-python)
qa-built-in.md:问题 (http://stackoverflow.com/questions/13857/can-you-explain-closures-as-they-relate-to-python)
qa-built-in.md:问题 (http://stackoverflow.com/questions/890128/python-lambda-why)
qa-built-in.md:问题 (http://stackoverflow.com/questions/1436703/difference-between-str-and-repr-in-python)
qa-control-flow.md:问题 (http://stackoverflow.com/questions/73663/terminating-a-python-script)
qa-control-flow.md:问题 (http://stackoverflow.com/questions/26595/is-there-any-difference-between-foo-is-none-and-foo-none)
qa-control-flow.md:问题 (http://stackoverflow.com/questions/522563/accessing-the-index-in-python-for-loops)
qa-control-flow.md:问题 (http://stackoverflow.com/questions/53162/how-can-i-do-a-line-break-line-continuation-in-python)
qa-control-flow.md:问题 (http://stackoverflow.com/questions/9284350/why-does-1-in-1-0-true-evaluate-to-false)
qa-control-flow.md:问题 (http://stackoverflow.com/questions/60208/replacements-for-switch-statement-in-python)
qa-control-flow.md:问题 (http://stackoverflow.com/questions/2710940/python-if-x-is-not-none-or-if-not-x-is-none)
qa-control-flow.md:问题 (http://stackoverflow.com/questions/423379/using-global-variables-in-a-function-other-than-the-one-that-created-them)
qa-control-flow.md:问题 (http://stackoverflow.com/questions/843277/how-do-i-check-if-a-variable-exists-in-python)
qa-control-flow.md:问题 (http://stackoverflow.com/questions/394809/does-python-have-a-ternary-conditional-operator)
qa-control-flow.md:问题 (http://stackoverflow.com/questions/743164/do-while-loop-in-python)
qa-control-flow.md:问题 (http://stackoverflow.com/questions/135041/should-you-always-favor-xrange-over-range)
qa-control-flow.md:问题 (http://stackoverflow.com/questions/15376509/when-is-i-x-different-from-i-i-x-in-python)
qa-datetime.md:问题 (http://stackoverflow.com/questions/1697815/how-do-you-convert-a-python-time-struct-time-object-into-a-datetime-object)
qa-datetime.md:问题 (http://stackoverflow.com/questions/415511/how-to-get-current-time-in-python)
qa-datetime.md:问题 (http://stackoverflow.com/questions/85451/python-time-clock-vs-time-time-accuracy)
qa-datetime.md:问题 (JSON datetime between Python and JavaScript)
qa-dict.md:问题 (http://stackoverflow.com/questions/1747817/python-create-a-dictionary-with-list-comprehension)
qa-dict.md:问题 (http://stackoverflow.com/questions/1323410/has-key-or-in)
qa-dict.md:问题 (http://stackoverflow.com/questions/1602934/check-if-a-given-key-already-exists-in-a-dictionary)
qa-dict.md:问题 (http://stackoverflow.com/questions/1024847/add-to-a-dictionary-in-python)
qa-dict.md:问题 (http://stackoverflow.com/questions/1305532/convert-python-dict-to-object)
qa-dict.md:问题 (http://stackoverflow.com/questions/38987/how-can-i-merge-union-two-python-dictionaries-in-a-single-expression)
qa-dict.md:问题 (http://stackoverflow.com/questions/209840/map-two-lists-into-a-dictionary-in-python)
qa-dict.md:问题 (http://stackoverflow.com/questions/72899/in-python-how-do-i-sort-a-list-of-dictionaries-by-values-of-the-dictionary)
qa-dict.md:问题 (http://stackoverflow.com/questions/613183/python-sort-a-dictionary-by-value)
qa-dict.md:问题 (http://stackoverflow.com/questions/4901815/object-as-a-dictionary-key)
qa-exception.md:问题 (http://stackoverflow.com/questions/1319615/proper-way-to-declare-custom-exceptions-in-modern-python)
qa-exception.md:问题 (http://stackoverflow.com/questions/2052390/how-do-i-manually-throw-raise-an-exception-in-python)
qa-exception.md:问题 (http://stackoverflow.com/questions/6470428/catch-multiple-exceptions-in-one-line-except-block)
qa-exception.md:问题 (http://stackoverflow.com/questions/944592/best-practice-for-python-assert)
qa-exception.md:问题 (http://stackoverflow.com/questions/5574702/how-to-print-to-stderr-in-python)
qa-exception.md:问题 (http://stackoverflow.com/questions/944592/best-practice-for-python-assert)
qa-file.md:问题 (http://stackoverflow.com/questions/82831/how-do-i-check-if-a-file-exists-using-python)
qa-file.md:问题 (http://stackoverflow.com/questions/273192/python-best-way-to-create-directory-if-it-doesnt-exist-for-file-write)
qa-file.md:问题 (http://stackoverflow.com/questions/123198/how-do-i-copy-a-file-in-python)
qa-file.md:问题 (http://stackoverflow.com/questions/275018/how-can-i-remove-chomp-a-newline-in-python)
qa-file.md:问题 (http://stackoverflow.com/questions/237079/how-to-get-file-creation-modification-date-times-in-python)
qa-file.md:问题 (http://stackoverflow.com/questions/466345/converting-string-into-datetime)
qa-file.md:问题 (http://stackoverflow.com/questions/5137497/find-current-directory-and-files-directory)
qa-file.md:问题 (http://stackoverflow.com/questions/3964681/find-all-files-in-directory-with-extension-txt-with-python)
qa-file.md:问题 (http://stackoverflow.com/questions/3277503/python-read-file-line-by-line-into-array)
qa-file.md:问题 (http://stackoverflow.com/questions/4706499/how-do-you-append-to-file-in-python)
qa-file.md:问题 (http://stackoverflow.com/questions/541390/extracting-extension-from-filename-in-python)
qa-file.md:问题 (http://stackoverflow.com/questions/3207219/how-to-list-all-files-of-a-directory-in-python)
qa-file.md:问题 (http://stackoverflow.com/questions/1450393/how-do-you-read-from-stdin-in-python)
qa-file.md:问题 (http://stackoverflow.com/questions/845058/how-to-get-line-count-cheaply-in-python)
qa-file.md:问题 (http://stackoverflow.com/questions/600268/mkdir-p-functionality-in-python)
qa-func.md:问题 (http://stackoverflow.com/questions/251464/how-to-get-the-function-name-as-string-in-python)
qa-func.md:问题 (http://stackoverflow.com/questions/3061/calling-a-function-from-a-string-with-the-functions-name-in-python)
qa-func.md:问题 (http://stackoverflow.com/questions/36901/what-does-double-star-and-star-do-for-python-parameters)
qa-func.md:问题 (http://stackoverflow.com/questions/1098549/proper-way-to-use-kwargs-in-python)
qa-func.md:问题 (http://stackoverflow.com/questions/3394835/args-and-kwargs)
qa-func.md:问题 (http://stackoverflow.com/questions/682504/what-is-a-clean-pythonic-way-to-have-multiple-constructors-in-python)
qa-func.md:问题 (http://stackoverflow.com/questions/36901/what-does-double-star-and-star-do-for-python-parameters)
qa-func.md:问题 (http://stackoverflow.com/questions/11241523/why-does-python-code-run-faster-in-a-function)
qa-func.md:问题 (http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference)
qa-list.md:问题 (http://stackoverflow.com/questions/509211/the-python-slice-notation)
qa-list.md:问题 (http://stackoverflow.com/questions/53513/python-what-is-the-best-way-to-check-if-a-list-is-empty)
qa-list.md:问题 (http://stackoverflow.com/questions/1720421/merge-two-lists-in-python)
qa-list.md:问题 (http://stackoverflow.com/questions/518021/getting-the-length-of-an-array-in-python)
qa-list.md:问题 (http://stackoverflow.com/questions/2612802/how-to-clone-a-list-in-python)
qa-list.md:问题 (http://stackoverflow.com/questions/252703/python-append-vs-extend)
qa-list.md:问题 (http://stackoverflow.com/questions/306400/how-do-i-randomly-select-an-item-from-a-list-using-python)
qa-list.md:问题 (http://stackoverflow.com/questions/627435/how-to-remove-an-element-from-a-list-by-index-in-python)
qa-list.md:问题 (http://stackoverflow.com/questions/930397/how-to-get-the-last-element-of-a-list)
qa-list.md:问题 (http://stackoverflow.com/questions/312443/how-do-you-split-a-list-into-evenly-sized-chunks-in-python)
qa-list.md:问题 (http://stackoverflow.com/questions/480214/how-do-you-remove-duplicates-from-a-list-in-python-whilst-preserving-order)
qa-list.md:问题 (http://stackoverflow.com/questions/1207406/remove-items-from-a-list-while-iterating-in-python)
qa-list.md:问题 (http://stackoverflow.com/questions/176918/in-python-how-do-i-find-the-index-of-an-item-given-a-list-containing-it)
qa-list.md:问题 (http://stackoverflow.com/questions/952914/making-a-flat-list-out-of-list-of-lists-in-python)
qa-list.md:问题 (http://stackoverflow.com/questions/1247486/python-list-comprehension-vs-map)
qa-list.md:问题 (http://stackoverflow.com/questions/626759/whats-the-difference-between-list-and-tuples)
qa-list.md:问题 (http://stackoverflow.com/questions/17160162/what-is-in-python-2-7)
qa-math.md:问题 (http://stackoverflow.com/questions/1476/how-do-you-express-binary-literals-in-python)
qa-math.md:问题 (http://stackoverflow.com/questions/209513/convert-hex-string-to-int-in-python)
qa-math.md:问题 (http://stackoverflow.com/questions/1267869/how-can-i-force-division-to-be-floating-point-in-python)
qa-math.md:问题 (http://stackoverflow.com/questions/961632/converting-integer-to-string-in-python)
qa-math.md:问题 (http://stackoverflow.com/questions/306313/python-is-operator-behaves-unexpectedly-with-integers)
qa-math.md:问题 (http://stackoverflow.com/questions/455612/limiting-floats-to-two-decimal-points)
qa-math.md:问题 (http://stackoverflow.com/questions/432842/how-do-you-get-the-logical-xor-of-two-variables-in-python)
qa-math.md:问题 (http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python)
qa-math.md:问题 (http://stackoverflow.com/questions/1485841/behaviour-of-increment-and-decrement-operators-in-python)
qa-modules.md:问题 (http://stackoverflow.com/questions/448271/what-is-init-py-for)
qa-modules.md:问题 (http://stackoverflow.com/questions/67631/how-to-import-a-module-given-the-full-path)
qa-modules.md:问题 (http://stackoverflow.com/questions/247770/retrieving-python-module-path)
qa-modules.md:问题 (http://stackoverflow.com/questions/44834/can-someone-explain-all-in-python)
qa-modules.md:问题 (http://stackoverflow.com/questions/437589/how-do-i-unload-reload-a-python-module)
qa-modules.md:问题 (http://stackoverflow.com/questions/36932/how-can-i-represent-an-enum-in-python)
qa-modules.md:问题 (http://stackoverflow.com/questions/419163/what-does-if-name-main-do)
qa-modules.md:问题 (http://stackoverflow.com/questions/279237/import-a-module-from-a-relative-path)
qa-modules.md:问题 (http://stackoverflow.com/questions/72852/how-to-do-relative-imports-in-python)
qa-oop.md:问题 (http://stackoverflow.com/questions/2709821/python-self-explained)
qa-oop.md:问题 (http://stackoverflow.com/questions/70528/why-are-pythons-private-methods-not-actually-private)
qa-oop.md:问题 (http://stackoverflow.com/questions/38238/what-are-class-methods-in-python-for)
qa-oop.md:问题 (http://stackoverflow.com/questions/674304/pythons-use-of-new-and-init)
qa-oop.md:问题 (http://stackoverflow.com/questions/510972/getting-the-class-name-of-an-instance-in-python)
qa-oop.md:问题 (http://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python)
qa-oop.md:问题 (http://stackoverflow.com/questions/735975/static-methods-in-python)
qa-oop.md:问题 (http://stackoverflow.com/questions/68645/static-class-variables-in-python)
qa-oop.md:问题 (http://stackoverflow.com/questions/610883/how-to-know-if-an-object-has-an-attribute-in-python)
qa-oop.md:问题 (http://stackoverflow.com/questions/31875/is-there-a-simple-elegant-way-to-define-singletons-in-python)
qa-oop.md:问题 (http://stackoverflow.com/questions/576169/understanding-python-super-and-init-methods)
qa-oop.md:问题 (http://stackoverflow.com/questions/1952464/in-python-how-do-i-determine-if-an-object-is-iterable)
qa-oop.md:问题 (http://stackoverflow.com/questions/19151/build-a-basic-python-iterator)
qa-oop.md:问题 (http://stackoverflow.com/questions/372042/difference-between-abstract-class-and-interface-in-python)
qa-oop.md:问题 (http://stackoverflow.com/questions/472000/python-slots)
qa-oop.md:问题 (http://stackoverflow.com/questions/54867/old-style-and-new-style-classes-in-python)
qa-oop.md:问题 (http://stackoverflow.com/questions/6618002/python-property-versus-getters-and-setters)
qa-oop.md:问题 (http://stackoverflow.com/questions/904036/chain-calling-parent-constructors-in-python)
qa-oop.md:问题 (http://stackoverflow.com/questions/1301346/the-meaning-of-a-single-and-a-double-underscore-before-an-object-name-in-python)
qa-oop.md:问题 (http://stackoverflow.com/questions/972/adding-a-method-to-an-existing-object)
qa-oop.md:问题 (http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python/6581949#6581949)
qa-oop.md:问题 (http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument)
qa-others.md:问题 (http://stackoverflow.com/questions/170921/should-i-learn-python-2-before-3-or-start-directly-from-python-3)
qa-others.md:问题 (http://stackoverflow.com/questions/1534210/use-different-python-version-with-virtualenv)
qa-others.md:问题 (http://stackoverflow.com/questions/990754/how-to-leave-a-python-virtualenv)
qa-others.md:问题 (http://stackoverflow.com/questions/193161/what-is-the-best-project-structure-for-a-python-application)
qa-others.md:问题 (http://stackoverflow.com/questions/13311094/counter-in-collections-module-python)
qa-others.md:问题 (http://stackoverflow.com/questions/372885/how-do-i-connect-to-a-mysql-database-in-python)
qa-others.md:问题 (http://stackoverflow.com/questions/4941145/python-flask-vs-bottle)
qa-others.md:问题 (http://stackoverflow.com/questions/582336/how-can-you-profile-a-python-script)
qa-others.md:问题 (http://stackoverflow.com/questions/2775864/python-create-unix-timestamp-five-minutes-in-the-future)
qa-others.md:问题 (http://stackoverflow.com/questions/89228/calling-an-external-command-in-python)
qa-others.md:问题 (http://stackoverflow.com/questions/287871/print-in-terminal-with-colors-using-python)
qa-others.md:问题 (http://stackoverflow.com/questions/261638/how-do-i-protect-python-code)
qa-others.md:问题 (http://stackoverflow.com/questions/191673/preferred-python-unit-testing-framework)
qa-others.md:问题 (http://stackoverflow.com/questions/61151/where-do-the-python-unit-tests-go)
qa-others.md:问题 (http://stackoverflow.com/questions/6344076/differences-between-distribute-distutils-setuptools-and-distutils2)
qa-pip-easy_install.md:问题 (http://stackoverflow.com/questions/2720014/upgrading-all-packages-with-pip)
qa-pip-easy_install.md:问题 (http://stackoverflow.com/questions/1231688/how-do-i-remove-packages-installed-with-pythons-easy-install)
qa-pip-easy_install.md:问题 (http://stackoverflow.com/questions/122327/how-do-i-find-the-location-of-my-python-site-packages-directory)
qa-pip-easy_install.md:问题 (http://stackoverflow.com/questions/1550226/python-setup-py-uninstall)
qa-pip-easy_install.md:问题 (http://stackoverflow.com/questions/739993/get-a-list-of-installed-python-modules)
qa-pip-easy_install.md:问题 (http://stackoverflow.com/questions/3220404/why-use-pip-over-easy-install)
qa-pip-easy_install.md:问题 (http://stackoverflow.com/questions/4324558/whats-the-proper-way-to-install-pip-virtualenv-and-distribute-for-python)
qa-std-modules.md:问题 (http://stackoverflow.com/questions/712791/json-and-simplejson-module-differences-in-python)
qa-std-modules.md:问题 (http://stackoverflow.com/questions/22676/how-do-i-download-a-file-over-http-using-python)
qa-std-modules.md:问题 (http://stackoverflow.com/questions/4480075/argparse-optional-positional-arguments)
qa-std-modules.md:问题 (http://stackoverflow.com/questions/842059/is-there-a-portable-way-to-get-the-current-username-in-python)
qa-std-modules.md:问题 (http://stackoverflow.com/questions/1912434/how-do-i-parse-xml-in-python)
qa-std-modules.md:问题 (http://stackoverflow.com/questions/534839/how-to-create-a-guid-in-python)
qa-std-modules.md:问题 (http://stackoverflow.com/questions/2018026/should-i-use-urllib-or-urllib2-or-requests)
qa-std-modules.md:问题 (http://stackoverflow.com/questions/192109/is-there-a-function-in-python-to-print-all-the-current-properties-and-values-of)
qa-std-modules.md:问题 (http://stackoverflow.com/questions/132058/showing-the-stack-trace-from-a-running-python-application)
qa-std-modules.md:问题 (http://stackoverflow.com/questions/1549801/differences-between-isinstance-and-type-in-python)
qa-std-modules.md:问题 (http://stackoverflow.com/questions/323972/is-there-any-way-to-kill-a-thread-in-python)
qa-string.md:问题 (http://stackoverflow.com/questions/493819/python-join-why-is-it-string-joinlist-instead-of-list-joinstring)
qa-string.md:问题 (http://stackoverflow.com/questions/6797984/how-to-convert-string-to-lowercase-in-python)
qa-string.md:问题 (http://stackoverflow.com/questions/931092/reverse-a-string-in-python)
qa-string.md:问题 (http://stackoverflow.com/questions/3437059/does-python-have-a-string-contains-method)
qa-string.md:问题 (http://stackoverflow.com/questions/354038/how-do-i-check-if-a-string-is-a-number-in-python)
qa-string.md:问题 (http://stackoverflow.com/questions/5082452/python-string-formatting-vs-format)
qa-string.md:问题 (http://stackoverflow.com/questions/988228/converting-a-string-to-dictionary)
qa-string.md:问题 (http://stackoverflow.com/questions/227459/ascii-value-of-a-character-in-python)
qa-string.md:问题 (http://stackoverflow.com/questions/1059559/python-strings-split-with-multiple-separators)
qa-string.md:问题 (http://stackoverflow.com/questions/1185524/how-to-trim-whitespace-including-tabs)
qa-string.md:问题 (http://stackoverflow.com/questions/663171/is-there-a-way-to-substring-a-string-in-python)
qa-string.md:问题 (http://stackoverflow.com/questions/1504717/python-vs-is-comparing-strings-is-fails-sometimes-why)
qa-string.md:问题 (http://stackoverflow.com/questions/339007/python-nicest-way-to-pad-zeroes-to-string)
qa-string.md:问题 (http://stackoverflow.com/questions/606191/convert-byte-array-to-python-string)
### contributors
thx a lot:)
- [wklken](https://github.com/wklken)
- [shnode](https://github.com/shnode)
more [link](https://github.com/wklken/stackoverflow-py-top-qa/graphs/contributors)
### Donation
You can Buy me a coffee:) [link](http://www.wklken.me/pages/donation.html)
------
To Be Continue ...
wklken
Email: wklken@yeah.net
Blog: http://wklken.me
2013-09-21 于深圳
================================================
FILE: contents/qa-built-in.md
================================================
### 如何flush Python的print输出
问题 [链接](http://stackoverflow.com/questions/230751/how-to-flush-output-of-python-print)
重复问题 [链接](http://stackoverflow.com/questions/107705/python-output-buffering)
默认print输出到sys.stdout
import sys
sys.stdout.flush()
参考
[http://docs.python.org/reference/simple_stmts.html#the-print-statement](http://docs.python.org/2/reference/simple_stmts.html#the-print-statement)
[http://docs.python.org/library/sys.html](http://docs.python.org/2/library/sys.html)
[http://docs.python.org/library/stdtypes.html#file-objects](http://docs.python.org/2/library/stdtypes.html#file-objects)
### Python如何检查一个对象是list或者tuple,但是不是一个字符串
问题 [链接](http://stackoverflow.com/questions/1835018/python-check-if-an-object-is-a-list-or-tuple-but-not-string)
原来的做法是
assert isinstance(lst, (list, tuple))
有没有更好的做法
我认为下面的方式是你需要的
assert not isinstance(lst, basestring)
原来的方式,你可能会漏过很多像列表,但并非list/tuple的
### Python中检查类型的权威方法
问题 [链接](http://stackoverflow.com/questions/152580/whats-the-canonical-way-to-check-for-type-in-python)
检查一个对象是否是给定类型或者对象是否继承于给定类型?
比如给定一个对象o,如何判断是不是一个str
检查是否是str
type(o) is str
检查是否是str或者str的子类
isinstance(o, str)
下面的方法在某些情况下有用
issubclass(type(o), str)
type(o) in ([str] + str.__subclasses__())
注意,你或许想要的是
isinstance(o, basestring)
因为unicode字符串可以满足判定(unicode 不是str的子类,但是str和unicode都是basestring的子类)
可选的,isinstance可以接收多个类型参数,只要满足其中一个即True
isinstance(o, (str, unicode))
### 如何判断一个变量的类型
问题 [链接](http://stackoverflow.com/questions/402504/how-to-determine-the-variable-type-in-python)
使用type
>>> i = 123
>>> type(i)
<type 'int'>
>>> type(i) is int
True
>>> i = 123456789L
>>> type(i)
<type 'long'>
>>> type(i) is long
True
>>> i = 123.456
>>> type(i)
<type 'float'>
>>> type(i) is float
True
另外一个相同的问题 [链接](http://stackoverflow.com/questions/2225038/python-determine-the-type-of-an-object)
>>> type( [] ) == list
True
>>> type( {} ) == dict
True
>>> type( "" ) == str
True
>>> type( 0 ) == int
True
>>> class Test1 ( object ):
pass
>>> class Test2 ( Test1 ):
pass
>>> a = Test1()
>>> b = Test2()
>>> type( a ) == Test1
True
>>> type( b ) == Test2
True
>>> type( b ) == Test1
False
>>> isinstance( b, Test1 )
True
>>> isinstance( b, Test2 )
True
>>> isinstance( a, Test1 )
True
>>> isinstance( a, Test2 )
False
>>> isinstance( [], list )
True
>>> isinstance( {}, dict )
True
### Python中如何注释一段代码块/为什么Python没有多行注释
问题 [链接](http://stackoverflow.com/questions/675442/comment-out-a-python-code-block)
问题 [链接](http://stackoverflow.com/questions/397148/why-doesnt-python-have-multiline-comments)
Python中多行注释的方式是
#print "hello"
#print "world"
注意,不要使用多行字符串对代码块进行注释,除非是文档字符串docstring.
### Python中单引号和双引号
问题 [链接](http://stackoverflow.com/questions/56011/single-quotes-vs-double-quotes-in-python)
根据文档,两者貌似没什么区别,有什么风格上的使用建议么?
我偏好于
双引号: 用于插入/改写的字符串, 自然语言消息
单引号: 标识符字符串,例如字典key. 除非该字符串本身有单括号或者我忘了
三引号: 文档字符串docstring 或者 正则表达式中原始字符串raw string
例如:
LIGHT_MESSAGES = {
'English': "There are %(number_of_lights)s lights.",
'Pirate': "Arr! Thar be %(number_of_lights)s lights."
}
def lights_message(language, number_of_lights):
"""Return a language-appropriate string reporting the light count."""
return LIGHT_MESSAGES[language] % locals()
def is_pirate(message):
"""Return True if the given message sounds piratical."""
return re.search(r"(?i)(arr|avast|yohoho)!", message) is not None
这里很偏个人风格,所以,根据自己喜好,保持一致就行
### 你是否能解释Python中的闭包
问题 [链接](http://stackoverflow.com/questions/13857/can-you-explain-closures-as-they-relate-to-python)
参考文章 [Closure on closures](http://mrevelle.blogspot.com/2006/10/closure-on-closures.html)
对象是数据和方法关联
闭包是函数和数据关联
例如
def make_counter():
i = 0
def counter(): # counter() is a closure
nonlocal i
i += 1
return i
return counter
c1 = make_counter()
c2 = make_counter()
print (c1(), c1(), c2(), c2())
# -> 1 2 1 2
其他解释(感觉英文更精准)
A function that references variables from a containing scope, potentially after flow-of-control has left that scope
A function that can refer to environments that are no longer active.
A closure allows you to bind variables into a function without passing them as parameters.
### Python Lambda - why?
问题 [链接](http://stackoverflow.com/questions/890128/python-lambda-why)
Are you talking about lambda functions? Like
你是指lambda函数? 例如
f = lambda x: x**2 + 2*x - 5
非常有用, python支持函数式编程, 你可以将函数作为参数进行传递去做一些事情
例子:
mult3 = filter(lambda x: x % 3 == 0, [1, 2, 3, 4, 5, 6, 7, 8, 9])
# sets mult3 to [3, 6, 9]
这样相对于完整地函数更为简短
def filterfunc(x):
return x % 3 == 0
mult3 = filter(filterfunc, [1, 2, 3, 4, 5, 6, 7, 8, 9])
当然, 这个例子你也可以使用列表解析进行处理
mult3 = [x for x in [1, 2, 3, 4, 5, 6, 7, 8, 9] if x % 3 == 0]
甚至是
range(3,10,3)
lambda function may be the shortest way to write something out
### Python中__str__和__repr__的区别
问题[链接](http://stackoverflow.com/questions/1436703/difference-between-str-and-repr-in-python)
Alex总结的很好,但是,有点出乎意料的精简了。
首先,让我重复一下Alex回答的重点:
- 缺省实现是没用的(很难想象,但是的确是这样的)
- `__repr__`的目的是清晰
- `__str__`的目的是可读性
- 容器的`__str__`使用已包含对象`__repr__`
**缺省实现是没用的**
这实在是奇怪,因为Python的缺省实现是为了完全的可用。然而,在这种情况下,使用缺省的`__repr__`会表现的像这样:
return "%s(%r)" % (self.__class__, self.__dict__)
这很危险(举个例子。如果对象被引用,太容易陷入无限循环)。所以,Python选择逃避。注意有一个缺省是正确的:如果`__repr__`已经定义,而`__str__`没有,对象会表现出`__str__=__repr__`。
这意味着,简单讲:几乎所有你实现的对象都应该有一个`__repr__`函数用来理解这个对象。实现`__str__`是一个选择:如果你需要一个"良好的打印”函数(举个例子,用来表现一个生成器)
**`__repr__`的目标是清晰的**
让我实话实说-我并不相信调试器。我不知道如何使用任何一种调试器,而且没有认真使用过任何一款。我觉的调试器的最大错误是它们的本质--我调试错误发生在很久很久以前,超级久远。这意味着我有着宗教热情一般的相信日志。日志是一切一劳永逸的服务器系统的生命之血。Python可以轻松的记录日志:可能某些项目有特殊的包装,但是你需要的仅仅是一句:
(INFO, "I am in the weird function and a is", a, "and b is", b, "but I got a null C — using default", default_c)
但是你需要做最后一步,所有你实现的对象有一个有效的repr,所以上面这种代码才会工作。这就是为什么"eval"这种东西出现:如果你又足够的信息可以让`eval(repr(c)) == c`,这意味着你知道所有的东西,像知道`c`一样。如果它足够简单,至少通过模糊的方法,实现它。如果不是这样的,请无论如何了解`c`的足够信息。我通常使用一个类eval的格式:`"My class(this=%r, that=%r)" % (self.this, self.that)"`。这不意味着你可以真正的结构化MyClass或者他们全都是正确的结构器参数。但是他们是很有用的形式代表“这个实例中你需要了解的信息就是这些”。
注意:我用的是`%r`而不是`%s`。你总是想用`repr()`[或者`%r`格式等效的角色]在一个可实现的`__repr__`中,或者你被repr的目的打败的。你需要知道`MyClass(3)`和`Myclass("3")`的区别。
**`__str__`的目标是可读性**
实际上,它不是为了更清晰--注意`str(3) == str("3")`。同样的,如果你实现了一个IP的抽象,有一个字符串看上去像192.168.1.1是Ok的。当实现一个日期或时间的抽象时,字符串可以是“2014/4/12 15:35:33"等等。所以它的目标是通过一种方式让用户,而不是一个程序员,可以正常的阅读它。去掉那些无用的字码,假装成其他的类--在它支持可读性之后,这是一种进化。
**容器的`__str__`使用已包含对象`__repr__`
这看上去很奇怪,是不是?确实有一点,但是可读性是这样:
[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]
吗?不一定。尤其是,容器内部的字符串会找到一个很容易实现的方式去构建它们所代表的东西。面对这种含糊不清的东西,记住,Python禁止猜测。如果你打印一个列表,想要上述的表现形式时,只需要
print "["+", ".join(l)+"]"
(你应该会想出如何处理字典)
**总结**
为你所有实现的类,实现`__repr__`。这应该是第二特性。实现`__str__`,对于那些你认为使用可视化字符串会更好的表现出错误的可读性,并阻止含糊不清的东西。
================================================
FILE: contents/qa-control-flow.md
================================================
### 如何结束退出一个python脚本
问题 [链接](http://stackoverflow.com/questions/73663/terminating-a-python-script)
import sys
sys.exit()
### foo is None 和 foo == None的区别
问题 [链接](http://stackoverflow.com/questions/26595/is-there-any-difference-between-foo-is-none-and-foo-none)
if foo is None: pass
if foo == None: pass
如果比较相同的对象实例,is总是返回True
而 == 最终取决于 "__eq__()"
>>> class foo(object):
def __eq__(self, other):
return True
>>> f = foo()
>>> f == None
True
>>> f is None
False
>>> list1 = [1, 2, 3]
>>> list2 = [1, 2, 3]
>>> list1==list2
True
>>> list1 is list2
False
另外
(ob1 is ob2) 等价于 (id(ob1) == id(ob2))
### 如何在循环中获取下标
问题 [链接](http://stackoverflow.com/questions/522563/accessing-the-index-in-python-for-loops)
使用enumerate
for idx, val in enumerate(ints):
print idx, val
### python中如何将一行长代码切成多行
问题 [链接](http://stackoverflow.com/questions/53162/how-can-i-do-a-line-break-line-continuation-in-python)
例如:
e = 'a' + 'b' + 'c' + 'd'
变成
e = 'a' + 'b' +
'c' + 'd'
括号中,可以直接换行
a = dostuff(blahblah1, blahblah2, blahblah3, blahblah4, blahblah5,
blahblah6, blahblah7)
非括号你可以这么做
a = '1' + '2' + '3' + \
'4' + '5'
或者
a = ('1' + '2' + '3' +
'4' + '5')
可以查看下代码风格: [style guide](http://www.python.org/dev/peps/pep-0008/)
推荐是后一种,但某些个别情况下,加入括号会导致错误
### 为何1 in [1,0] == True执行结果是False
问题 [链接](http://stackoverflow.com/questions/9284350/why-does-1-in-1-0-true-evaluate-to-false)
有如下
>>> 1 in [1,0] # This is expected
True
>>> 1 in [1,0] == True # This is strange
False
>>> (1 in [1,0]) == True # This is what I wanted it to be
True
>>> 1 in ([1,0] == True) # But it's not just a precedence issue!
# It did not raise an exception on the second example.
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
1 in ([1,0] == True)
TypeError: argument of type 'bool' is not iterable
这里python使用了比较运算符链
1 in [1,0] == True
将被转为
(1 in [1, 0]) and ([1, 0] == True)
很显然是false的
同样的
a < b < c
会被转为
(a < b) and (b < c) # b不会被解析两次
[具体文档](http://docs.python.org/2/reference/expressions.html#not-in)
### Python中的switch替代语法
问题 [链接](http://stackoverflow.com/questions/60208/replacements-for-switch-statement-in-python)
python中没有switch,有什么推荐的处理方法么
使用字典:
def f(x):
return {
'a': 1,
'b': 2,
}.get(x, 9)
Python Cookbook中的几种方式
[Readable switch construction without lambdas or dictionaries](http://code.activestate.com/recipes/410692/)
[Exception-based Switch-Case](http://code.activestate.com/recipes/410695/)
[Using a Dictionary in place of a 'switch' statement](http://code.activestate.com/recipes/181064/)
### 使用 'if x is not None' 还是'if not x is None'
问题 [链接](http://stackoverflow.com/questions/2710940/python-if-x-is-not-none-or-if-not-x-is-none)
我总想着使用 'if not x is None' 会更加简明
但是google的Python风格指南使用的却是 'if x is not None'
性能上没有什么区别,他们编译成相同的字节码
Python 2.6.2 (r262:71600, Apr 15 2009, 07:20:39)
>>> import dis
>>> def f(x):
... return x is not None
...
>>> dis.dis(f)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 0 (None)
6 COMPARE_OP 9 (is not)
9 RETURN_VALUE
>>> def g(x):
... return not x is None
...
>>> dis.dis(g)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 0 (None)
6 COMPARE_OP 9 (is not)
9 RETURN_VALUE
在风格上,我尽量避免 'not x is y' 这种形式,虽然编译器会认为和 'not (x is y)'一样,但是读代码的人或许会误解为 '(not x) is y'
如果写作 'x is not y' 就不会有歧义
最佳实践
if x is not None:
# Do something about x
### 在非创建全局变量的地方使用全局变量
问题 [链接](http://stackoverflow.com/questions/423379/using-global-variables-in-a-function-other-than-the-one-that-created-them)
如果我在一个函数中创建了全局变量,如何在另一个函数中使用?
回答:
你可以在给全局变量赋值的函数中声明 global
globvar = 0
def set_globvar_to_one():
global globvar # Needed to modify global copy of globvar
globvar = 1
def print_globvar():
print globvar # No need for global declaration to read value of globvar
set_globvar_to_one()
print_globvar() # Prints 1
我猜想这么做的原因是,全局变量很危险,Python想要确保你真的知道你要对一个全局的变量进行操作
如果你想知道如何在模块间使用全局变量,查看其他回答
### 如何检测一个变量是否存在
问题 [链接](http://stackoverflow.com/questions/843277/how-do-i-check-if-a-variable-exists-in-python)
我想检测一个变量是否存在,我现在是这么做的
try:
myVar
except NameError:
# Doint smth
存在其他不是使用exception的方式么?
回答
检测本地变量
if 'myVar' in locals():
# myVar exists.
检测全局变量
if 'myVar' in globals():
# myVar exists.
检测一个对象是否包含某个属性
if hasattr(obj, 'attr_name'):
# obj.attr_name exists.
### Python中是否存在三元运算符
问题 [链接](http://stackoverflow.com/questions/394809/does-python-have-a-ternary-conditional-operator)
三元运算在Python2.5中被加入
a if test else b
使用
>>> 'true' if True else 'false'
'true'
>>> 'true' if False else 'false'
'false'
官方文档:
[Conditional expressions](https://docs.python.org/3/reference/expressions.html#conditional-expressions)
[Is there an equivalent of C’s ”?:” ternary operator?](https://docs.python.org/3.3/faq/programming.html#is-there-an-equivalent-of-c-s-ternary-operator)
### Python中的do-while
问题 [链接](http://stackoverflow.com/questions/743164/do-while-loop-in-python)
实现方法
while True:
stuff()
if fail_condition:
break
或者
stuff()
while not fail_condition:
stuff()
### 相对于range() 应该更倾向于实用xrange()?
问题 [链接](http://stackoverflow.com/questions/135041/should-you-always-favor-xrange-over-range)
why or why not?
就性能而言, 特别是当你迭代一个大的range, xrange()更优. 但是, 有一些情况下range()更优
- 在Python3中, range() 等价于 python2.x的 xrange(), 而xrange()不存在了.(如果你的代码将在2和3下运行, 不能使用xrange)
- range()在某些情况下更快, 例如, 多次重复遍历同一个序列.
- xrange()并不适用于所有情况, 例如, 不支持slices以及任意的list方法
### 在Python中,“i += x”和“i = i + x”什么时候不等
问题[链接](http://stackoverflow.com/questions/15376509/when-is-i-x-different-from-i-i-x-in-python)
这完全取决于i这个对象。
`+=`调用了[`__iadd__`方法](https://docs.python.org/2/reference/datamodel.html#object.__iadd__)(如果存在—不存在就退一步调用`__add__`),然而`+`调用[`__add__`方法](https://docs.python.org/2/reference/datamodel.html#object.__add__)^1
从一个API的角度,`__iadd__`期望被使用在恰当的位置修改易变的对象(返回的对象也是转变后的),而`__add__`应该返回某些东西的一个新的实例。对于不可变对象,两种方法都返回新的实例,但`__iadd__`会把新的实例放在和旧实例名字相同的命名空间里。这就是为什么
i = 1
i += 1
看上去增量`i`,实际上,你得到了一个新的数值,并且转移到了`i`的最上面—丢掉了旧的数值的引用。在这种情况下,`i += 1`和`i = i + 1`是完全一样的。但是,对于大多数可变对象,这是完全不同的:
一个具体的例子:
a = [1, 2, 3]
b = a
b += [1, 2, 3]
print a #[1, 2, 3, 1, 2, 3]
print b #[1, 2, 3, 1, 2, 3]
对比一下:
a = [1, 2, 3]
b = a
b = b + [1, 2, 3]
print a #[1, 2, 3]
print b #[1, 2, 3, 1, 2, 3]
注意第一个例子,从`b`和`a`代表相同的对象开始,当我对`b`使用`+=`,实际上它改变了`b`(`a`看起来也改变了- -毕竟他们代表同一个列表)。但是在第二个例子里,当我进行`b = b + [1, 2, 3]`操作时,b被引用并且和一个新的列表`[1, 2, 3]`联系了起来。之后在b的命名空间保存了这个关联的列表- -不考虑b之前的序列。
================================================
FILE: contents/qa-datetime.md
================================================
### 如何将一个Python time.struct_time对象转换为一个datetime对象
问题 [链接](http://stackoverflow.com/questions/1697815/how-do-you-convert-a-python-time-struct-time-object-into-a-datetime-object)
使用 [time.mktime()]() 将time元组(本地时间)转成秒, 然后使用 datetime.fromtimestamp() 转成datetime对象
from time import mktime
from datetime import datetime
dt = datetime.fromtimestamp(mktime(struct))
### python中如何获取当前时间
问题 [链接](http://stackoverflow.com/questions/415511/how-to-get-current-time-in-python)
时间日期
>>> import datetime
>>> datetime.datetime.now()
datetime(2009, 1, 6, 15, 8, 24, 78915)
如果仅获取时间
>>> datetime.datetime.time(datetime.datetime.now())
datetime.time(15, 8, 24, 78915))
#等价
>>> datetime.datetime.now().time()
可以从文档中获取更多 [文档](http://docs.python.org/2/library/datetime.html)
如果想避免额外的datetime.
>>> from datetime import datetime
### Python - time.clock() vs. time.time() - 更精确?
问题 [链接](http://stackoverflow.com/questions/85451/python-time-clock-vs-time-time-accuracy)
哪一个更适合于计时? 哪个更精确,
例如
start = time.clock()
... do something
elapsed = (time.clock() - start)
and
start = time.time()
... do something
elapsed = (time.time() - start)
回答
区别
clock() -> floating point number
Return the CPU time or real time since the start of the process or since
the first call to clock().
This has as much precision as the system records.
time() -> floating point number
Return the current time in seconds since the Epoch.
Fractions of a second may be present if the system clock provides them.
根据 [time module doc](http://docs.python.org/lib/module-time.html)
clock()
On Unix, return the current processor time as a floating point number expressed in seconds. The precision, and in fact the very definition of the meaning of ``processor time'', depends on that of the C function of the same name,
but in any case, this is the function to use for benchmarking Python or timing algorithms.
简而言之, time.clock()更精确些, 但是如果涉及cpu外的硬件时间统计(e.g. gpu), 只能使用time.time()
另外基于性能的评估, 可以去看下timeit模块
### python和javascript中josn的datetime
问题 [链接](JSON datetime between Python and JavaScript)
怎样从python->javascript传递json的datetime?
可以`json.dumps`中加入`default`参数
>>> dthandler = lambda obj: (
... obj.isoformat()
... if isinstance(obj, datetime.datetime)
... or isinstance(obj, datetime.date)
... else None)
>>> json.dumps(datetime.datetime.now(), default=dthandler)
'"2010-04-20T20:08:21.634121"'
一个更好理解的handler
ef handler(obj):
if hasattr(obj, 'isoformat'):
return obj.isoformat()
elif isinstance(obj, ...):
return ...
else:
raise TypeError, 'Object of type %s with value of %s is not JSON serializable' % (type(obj), repr(obj))
但是上面这种做法, 对于json中包含其他的类型, 会返回None
import json
import datetime
class DateTimeJSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
return obj.isoformat()
else:
return super(DateTimeJSONEncoder, self).default(obj)
>>> DateTimeJSONEncoder().encode([datetime.datetime.now()])
'["2010-06-15T14:42:28"]'
================================================
FILE: contents/qa-dict.md
================================================
### 使用列表解析创建一个字典
问题 [链接](http://stackoverflow.com/questions/1747817/python-create-a-dictionary-with-list-comprehension)
python 2.6
d = dict((key, value) for (key, value) in sequence)
python 2.7+ or 3, 使用 [字典解析语法](http://www.python.org/dev/peps/pep-0274/)
d = {key: value for (key, value) in sequence}
### 使用"in"还是"has_key()"
问题 [链接](http://stackoverflow.com/questions/1323410/has-key-or-in)
d = {'a': 1, 'b': 2}
'a' in d
True
or:
d = {'a': 1, 'b': 2}
d.has_key('a')
True
哪种更好
in更pythonic, 另外 has_key()在Python3.x中已经被移除
### 字典默认值
问题 [链接](http://stackoverflow.com/questions/1602934/check-if-a-given-key-already-exists-in-a-dictionary)
和问题有点偏
#获取时,如不存在,得到默认值
d.get(key, 0)
#设置时,若key不存在,设置默认值,已存在,返回已存在value
d.setdefault(key, []).append(new_element)
#初始即默认值
from collections import defaultdict
d = defaultdict(lambda: 0)
#or d = defaultdict(int)
### 如何给字典添加一个值
问题 [链接](http://stackoverflow.com/questions/1024847/add-to-a-dictionary-in-python)
#### Making a dictionary ####
data = {}
# OR #
data = dict()
#### Initially adding values ####
data = {'a':1,'b':2,'c':3}
# OR #
data = dict(a=1, b=2, c=3)
#### Inserting/Updating value ####
data['a']=1 # updates if 'a' exists, else adds 'a'
# OR #
data.update({'a':1})
# OR #
data.update(dict(a=1))
#### Merging 2 dictionaries ####
data.update(data2) # Where data2 is also a dict.
### 如何将字段转换成一个object,然后使用对象-属性的方式读取
问题 [链接](http://stackoverflow.com/questions/1305532/convert-python-dict-to-object)
有dict
>>> d = {'a': 1, 'b': {'c': 2}, 'd': ["hi", {'foo': "bar"}]}
想用这种方式访问
>>> x = dict2obj(d)
>>> x.a
1
>>> x.b.c
2
>>> x.d[1].foo
bar
使用namedtuple
>>> from collections import namedtuple
>>> MyStruct = namedtuple('MyStruct', 'a b d')
>>> s = MyStruct(a=1, b={'c': 2}, d=['hi'])
>>> s
MyStruct(a=1, b={'c': 2}, d=['hi'])
>>> s.a
1
>>> s.b
{'c': 2}
>>> s.c
>>> s.d
['hi']
使用类
class Struct:
def __init__(self, **entries):
self.__dict__.update(entries)
>>> args = {'a': 1, 'b': 2}
>>> s = Struct(**args)
>>> s
<__main__.Struct instance at 0x01D6A738>
>>> s.a
1
>>> s.b
2
### 如何在单一表达式中合并两个Python字典
问题 [链接](http://stackoverflow.com/questions/38987/how-can-i-merge-union-two-python-dictionaries-in-a-single-expression)
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = x.update(y)
>>> print z
None
>>> x
{'a': 1, 'b': 10, 'c': 11}
我想要最终合并结果在z中,不是x,我要怎么做?
回答
这种情况下,可以使用
z = dict(x.items() + y.items())
这个表达式将会实现你想要的,最终结果z,并且相同key的值,将会是y中key对应的值
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = dict(x.items() + y.items())
>>> z
{'a': 1, 'c': 11, 'b': 10}
如果在Python3中,会变得有些复杂
>>> z = dict(list(x.items()) + list(y.items()))
>>> z
{'a': 1, 'c': 11, 'b': 10}
### 如何映射两个列表成为一个字典
问题 [链接](http://stackoverflow.com/questions/209840/map-two-lists-into-a-dictionary-in-python)
两个列表
keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')
如何得到
dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}
使用zip
>>> keys = ['a', 'b', 'c']
>>> values = [1, 2, 3]
>>> dictionary = dict(zip(keys, values))
>>> print dictionary
{'a': 1, 'b': 2, 'c': 3}
### 排序一个列表中的所有dict,根据dict内值
问题 [链接](http://stackoverflow.com/questions/72899/in-python-how-do-i-sort-a-list-of-dictionaries-by-values-of-the-dictionary)
如何排序如下列表,根据name或age
[{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]
简单的做法;
newlist = sorted(list_to_be_sorted, key=lambda k: k['name'])
高效的做法
from operator import itemgetter
newlist = sorted(list_to_be_sorted, key=itemgetter('name'))
### 根据值排序一个字典
问题 [链接](http://stackoverflow.com/questions/613183/python-sort-a-dictionary-by-value)
import operator
x = {1: 2, 3: 4, 4:3, 2:1, 0:0}
sorted_x = sorted(x.iteritems(), key=operator.itemgetter(1))
#[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]
#dict(sorted_x) == x
### 如何将自定义对象作为字典键值
问题 [链接](http://stackoverflow.com/questions/4901815/object-as-a-dictionary-key)
class MyThing:
def __init__(self,name,location,length):
self.name = name
self.location = location
self.length = length
def __hash__(self):
return hash((self.name, self.location))
def __eq__(self, other):
return (self.name, self.location) == (other.name, other.location)
================================================
FILE: contents/qa-exception.md
================================================
### Python中声明exception的方法
问题 [链接](http://stackoverflow.com/questions/1319615/proper-way-to-declare-custom-exceptions-in-modern-python)
在python2.6中定义异常得到警告
>>> class MyError(Exception):
... def __init__(self, message):
... self.message = message
...
>>> MyError("foo")
_sandbox.py:3: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
问题很长,大意如标题
回答
或许我理解错了,但是为什么不这样做
class MyException(Exception):
pass
如果要重写什么,例如传递额外参数,可以这么做
class ValidationError(Exception):
def __init__(self, message, Errors):
# Call the base class constructor with the parameters it needs
Exception.__init__(self, message)
# Now for your custom code...
self.Errors = Errors
你可以通过第二个参数传递error 字典, 之后通过e.Errors获取
### 如何人为地抛出一个异常
问题 [链接](http://stackoverflow.com/questions/2052390/how-do-i-manually-throw-raise-an-exception-in-python)
pythonic
raise Exception("I know python!")
更多可参考 [文档](http://docs.python.org/2/reference/simple_stmts.html#the-raise-statement)
### 如何一行内处理多个异常
问题 [链接](http://stackoverflow.com/questions/6470428/catch-multiple-exceptions-in-one-line-except-block)
我知道可以这么做
try:
# do something that may fail
except:
# do this if ANYTHING goes wrong
也可以
try:
# do something that may fail
except IDontLikeYourFaceException:
# put on makeup or smile
except YouAreTooShortException:
# stand on a ladder
如果想在一行里处理多个异常的话
try:
# do something that may fail
except IDontLIkeYouException, YouAreBeingMeanException: #没生效
except Exception, e: #捕获了所有
# say please
答案
# as在python2.6,python2.7中仍然可以使用
except (IDontLIkeYouException, YouAreBeingMeanException) as e:
pass
### Python assert最佳实践
问题 [链接](http://stackoverflow.com/questions/944592/best-practice-for-python-assert)
有没有代码实例使用assert作为独立代码,而不是仅用来debug
assert x >= 0, 'x is less than zero'
类似
if x < 0:
raise Exception, 'x is less than zero'
有什么方法,可以设定一个规则就像 if x \< 0 抛出错误但是不是通过try/except/finally检查的
搞晕了:
原文 Also, is there any way to set a business rule like if x \< 0 raise error that is always checked without the try/except/finally so, if at anytime throughout the code x is less than 0 an error is raised, like if you set assert x < 0 at the start of a function, anywhere within the function where x becomes less then 0 an exception is raised?
回答1
Assert仅用在,测试那些从不发生的情况!目的是让程序尽早失败
Exception用在,那些可以明确知道会发生的错误,并且建议总是创建自己的异常类
例如,你写一个函数从配置文件中读取配置放入字典,文件格式不正确抛出一个ConfigurationSyntaxError,同时你可以assert返回值非None
在你的例子中,如果x是通过用户接口或外部传递设置的,最好使用exception
如果x仅是同一个程序的内部代码,使用assert
回答2
这个函数是为了能够当x小于0的时候,原子性的抛出一个异常。你可以使用[class descriptors](https://docs.python.org/2/reference/datamodel.html#implementing-descriptors)有一个例子:
class ZeroException(Exception):
pass
class variable(object):
def __init__(self, value=0):
self.__x = value
def __set__(self, obj, value):
if value < 0:
raise ZeroException('x is less than zero')
self.__x = value
def __get__(self, obj, objType):
return self.__x
class MyClass(object):
x = variable()
>>> m = MyClass()
>>> m.x = 10
>>> m.x -= 20
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "my.py", line 7, in __set__
raise ZeroException('x is less than zero')
ZeroException: x is less than zero
### 如何打印到stderr
问题 [链接](http://stackoverflow.com/questions/5574702/how-to-print-to-stderr-in-python)
经常这么干
import sys
sys.stderr.write('spam\n')
print >> sys.stderr, 'spam'
from __future__ import print_function
print('spam', file=sys.stderr)
但是不够pythonic, 有没有更好的方法?
回答
我发现这种方式是最短/灵活/可扩展/可读的做法
from __future__ import print_function
def warning(*objs):
print("WARNING: ", *objs, file=sys.stderr)
================================================
FILE: contents/qa-file.md
================================================
### 如何判断一个文件是否存在
问题 [链接](http://stackoverflow.com/questions/82831/how-do-i-check-if-a-file-exists-using-python)
如何检查一个文件是否存在,不适用try:声明
import os.path
print os.path.isfile(fname)
print os.path.exists(fname)
### 如何创建不存在的目录结构
问题 [链接](http://stackoverflow.com/questions/273192/python-best-way-to-create-directory-if-it-doesnt-exist-for-file-write)
if not os.path.exists(directory):
os.makedirs(directory)
需要注意的是,当目录在exists和makedirs两个函数调用之间被创建时,makedirs将抛出OSError
### 如何拷贝一个文件
问题 [链接](http://stackoverflow.com/questions/123198/how-do-i-copy-a-file-in-python)
[shutil](http://docs.python.org/2/library/shutil.html)模块
copyfile(src, dst)
将src文件内容拷贝到dst,目标文件夹必须可写,否则将抛出IOError异常
如果目标文件已存在,将被覆盖
另外特殊文件,如字符文件和块设备文件,无法用这个方法进行拷贝
src/dst是字符串
### 逐行读文件去除换行符(perl chomp line)
问题 [链接](http://stackoverflow.com/questions/275018/how-can-i-remove-chomp-a-newline-in-python)
类似问题 [链接](http://stackoverflow.com/questions/761804/trimming-a-string-in-python)
读一个文件,如何获取每一行内容(不包括换行符)
比较pythonic的做法:
>>> text = "line 1\nline 2\r\nline 3\nline 4"
>>> text.splitlines()
['line 1', 'line 2', 'line 3', 'line 4']
用rstrip,(rstrip/lstrip/strip)
#去除了尾部的空白+换行
>>> 'test string \n'.rstrip()
'test string'
#只去换行
>>> 'test string \n'.rstrip('\n')
'test string '
#更通用的做法,系统相关
>>> import os, sys
>>> sys.platform
'linux2'
>>> "foo\r\n".rstrip(os.linesep)
'foo\r'
### 如何获取一个文件的创建和修改时间
问题 [链接](http://stackoverflow.com/questions/237079/how-to-get-file-creation-modification-date-times-in-python)
跨平台的获取文件创建及修改时间的方法
你有很多选择
使用[os.path.getmtime](http://docs.python.org/release/2.5.2/lib/module-os.path.html#l2h-2177)或者[os.path.getctime](http://docs.python.org/release/2.5.2/lib/module-os.path.html#l2h-2178)
import os.path, time
print "last modified: %s" % time.ctime(os.path.getmtime(file))
print "created: %s" % time.ctime(os.path.getctime(file))
或者[os.stat](http://www.python.org/doc/2.5.2/lib/module-stat.html)
import os, time
(mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime) = os.stat(file)
print "last modified: %s" % time.ctime(mtime)
注意,ctime()并非指*nix系统中文件创建时间,而是这个节点数据的最后修改时间
### 如何将字符串转换为datetime
问题 [链接](http://stackoverflow.com/questions/466345/converting-string-into-datetime)
可以查看下time模块的[strptime](http://docs.python.org/2/library/time.html#time.strptime)方法,反向操作是[strftime](http://docs.python.org/2/library/time.html#time.strftime)
from datetime import datetime
date_object = datetime.strptime('Jun 1 2005 1:33PM', '%b %d %Y %I:%M%p')
[扩展文档](http://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior)
### 找到当前目录及文件所在目录
问题 [链接](http://stackoverflow.com/questions/5137497/find-current-directory-and-files-directory)
查找当前目录使用os.getcwd()
查找某个文件的目录,使用, [os.path](http://docs.python.org/2/library/os.path.html)
import os.path
os.path.realpath(__file__)
### 如何找到一个目录下所有.txt文件
问题 [链接](http://stackoverflow.com/questions/3964681/find-all-files-in-directory-with-extension-txt-with-python)
使用[glob](http://docs.python.org/2/library/glob.html)
import glob
import os
os.chdir("/mydir")
for files in glob.glob("*.txt"):
print files
使用os.listdir
import os
os.chdir("/mydir")
for files in os.listdir("."):
if files.endswith(".txt"):
print files
或者遍历目录
import os
for r,d,f in os.walk("/mydir"):
for files in f:
if files.endswith(".txt"):
print os.path.join(r,files)
### 读文件到列表中
问题 [链接](http://stackoverflow.com/questions/3277503/python-read-file-line-by-line-into-array)
f = open('filename')
lines = f.readlines()
f.close()
等价
with open(fname) as f:
content = f.readlines()
[文档](http://docs.python.org/2/tutorial/inputoutput.html#reading-and-writing-files)
### 如何往文件中追加文本
问题 [链接](http://stackoverflow.com/questions/4706499/how-do-you-append-to-file-in-python)
with open("test.txt", "a") as myfile:
myfile.write("appended text")
可以使用'a'或'a+b' mode打开文件,见 [文档](http://docs.python.org/2/library/functions.html#open)
### 如何获取文件扩展名
问题 [链接](http://stackoverflow.com/questions/541390/extracting-extension-from-filename-in-python)
使用os.path.splitext方法:
>>> import os
>>> fileName, fileExtension = os.path.splitext('/path/to/somefile.ext')
>>> fileName
'/path/to/somefile'
>>> fileExtension
'.ext'
### 如何列出一个目录的所有文件
问题 [链接](http://stackoverflow.com/questions/3207219/how-to-list-all-files-of-a-directory-in-python)
1.使用os.listdir(),得到目录下的所有文件和文件夹
#只需要文件
from os import listdir
from os.path import isfile, join
onlyfiles = [ f for f in listdir(mypath) if isfile(join(mypath,f)) ]
2.os.walk()
from os import walk
f = []
for (dirpath, dirnames, filenames) in walk(mypath):
f.extend(filenames)
break
3.glob
import glob
print glob.glob("/home/adam/*.txt")
重复问题 [链接](http://stackoverflow.com/questions/120656/directory-listing-in-python)
import os
for dirname, dirnames, filenames in os.walk('.'):
# print path to all subdirectories first.
for subdirname in dirnames:
print os.path.join(dirname, subdirname)
# print path to all filenames.
for filename in filenames:
print os.path.join(dirname, filename)
### 如何从标准输入读取内容stdin
问题 [链接](http://stackoverflow.com/questions/1450393/how-do-you-read-from-stdin-in-python)
使用[fileinput](http://docs.python.org/2/library/fileinput.html)
import fileinput
for line in fileinput.input():
pass
### 如何高效地获取文件行数
问题 [链接](http://stackoverflow.com/questions/845058/how-to-get-line-count-cheaply-in-python)
比较结果python2.6
mapcount : 0.471799945831
simplecount : 0.634400033951
bufcount : 0.468800067902
opcount : 0.602999973297
代码
from __future__ import with_statement
import time
import mmap
import random
from collections import defaultdict
def mapcount(filename):
f = open(filename, "r+")
buf = mmap.mmap(f.fileno(), 0)
lines = 0
readline = buf.readline
while readline():
lines += 1
return lines
def simplecount(filename):
lines = 0
for line in open(filename):
lines += 1
return lines
def bufcount(filename):
f = open(filename)
lines = 0
buf_size = 1024 * 1024
read_f = f.read # loop optimization
buf = read_f(buf_size)
while buf:
lines += buf.count('\n')
buf = read_f(buf_size)
return lines
def opcount(fname):
with open(fname) as f:
for i, l in enumerate(f):
pass
return i + 1
counts = defaultdict(list)
for i in range(5):
for func in [mapcount, simplecount, bufcount, opcount]:
start_time = time.time()
assert func("big_file.txt") == 1209138
counts[func].append(time.time() - start_time)
for key, vals in counts.items():
print key.__name__, ":", sum(vals) / float(len(vals))
### Python如何实现mkdir -p功能
问题 [链接](http://stackoverflow.com/questions/600268/mkdir-p-functionality-in-python)
import os, errno
def mkdir_p(path):
try:
os.makedirs(path)
except OSError as exc: # Python >2.5
if exc.errno == errno.EEXIST and os.path.isdir(path):
pass
else: raise
================================================
FILE: contents/qa-func.md
================================================
### 如何获取一个函数的函数名字符串
问题 [链接](http://stackoverflow.com/questions/251464/how-to-get-the-function-name-as-string-in-python)
my_function.__name__
>>> import time
>>> time.time.__name__
'time'
### 用函数名字符串调用一个函数
问题 [链接](http://stackoverflow.com/questions/3061/calling-a-function-from-a-string-with-the-functions-name-in-python)
假设模块foo有函数bar:
import foo
methodToCall = getattr(foo, 'bar')
result = methodToCall()
或者一行搞定
result = getattr(foo, 'bar')()
### Python中\*\*和\*的作用
问题 [链接](http://stackoverflow.com/questions/36901/what-does-double-star-and-star-do-for-python-parameters)
\*args和\*\*kwargs允许函数拥有任意数量的参数,具体可以查看 [more on defining functions](http://docs.python.org/dev/tutorial/controlflow.html#more-on-defining-functions)
*args将函数所有参数转为序列
In [1]: def foo(*args):
...: for a in args:
...: print a
...:
...:
In [2]: foo(1)
1
In [4]: foo(1,2,3)
1
2
3
**kwargs 将函数所有关键字参数转为一个字典
In [5]: def bar(**kwargs):
...: for a in kwargs:
...: print a, kwargs[a]
...:
...:
In [6]: bar(name="one", age=27)
age 27
name one
两种用法可以组合使用
def foo(kind, *args, **kwargs):
pass
*l的另一个用法是用于函数调用时的参数列表解包(unpack)
In [9]: def foo(bar, lee):
...: print bar, lee
...:
...:
In [10]: l = [1,2]
In [11]: foo(*l)
1 2
在Python3.0中,可以将*l放在等号左边用于赋值 [Extended Iterable Unpacking](http://www.python.org/dev/peps/pep-3132/)
first, *rest = [1,2,3,4]
first, *l, last = [1,2,3,4]
### 在Python中使用\*\*kwargs的合适方法
问题 [链接](http://stackoverflow.com/questions/1098549/proper-way-to-use-kwargs-in-python)
当存在默认值的时候,如何合适的使用**kwargs?
kwargs返回一个字典,但是这是不是设置默认值的最佳方式?还是有其他方式?我只能将其作为一个字典接受,然后用get函数获取参数?
class ExampleClass:
def __init__(self, **kwargs):
self.val = kwargs['val']
self.val2 = kwargs.get('val2')
问题很简单,但是我没找到合适的解释。我见到人们用不同的方式实现,很难搞明白如何使用
回答
你可以用get函数给不在字典中的key传递一个默认值
self.val2 = kwargs.get('val2',"default value")
但是,如果你计划给一个特别的参数赋默认值,为什么不在前一个位置使用命名参数?
def __init__(self, val2="default value", **kwargs):
<<<<<<< HEAD
### 构造一个基本的Python迭代器
- 问题
[链接](http://stackoverflow.com/questions/19151/build-a-basic-python-iterator)
- 回答
python中的迭代器对象遵守迭代器协议,也就意味着python会提供两个方法:__iter__() 和 next().方法__iter__ 返回迭代器对象并且在循环开始时隐含调用.方法next()返回下一个值并且在每次循环中隐含调用.方法next()在没有任何值可返回时,抛出StopIteration异常.之后被循环构造器捕捉到而停止迭代.
下面是简单的计数器例子:
```python
class Counter:
def __init__(self, low, high):
self.current = low
self.high = high
def __iter__(self):
return self
def next(self): # Python 3: def __next__(self)
if self.current > self.high:
raise StopIteration
else:
self.current += 1
return self.current - 1
for c in Counter(3, 8):
print c
```
输出:
```python
3
4
5
6
7
8
```
使用生成器会更简单,包含了先前的回答:
```python
def counter(low, high):
current = low
while current <= high:
yield current
current += 1
for c in counter(3, 8):
print c
```
输出是一样的.本质上说,生成器对象支持迭代协议并且大致完成和计数器类相同的事情.
David Mertz的文章, [Iterators and Simple Generators](http://www.ibm.com/developerworks/library/l-pycon.html),是一个非常不错的介绍.
### \*args和\*\*kwargs是什么
问题[链接](http://stackoverflow.com/questions/3394835/args-and-kwargs)
真正的语法是`*`和`**`,`*args`和`**kwargs`这两个名字只是约定俗成的,但并没有硬性的规定一定要使用它们。
当你不确定有多少个参数会被传进你的函数时,你可能会使用`*args`,也就是说它允许你给你的函数传递任意数量的参数,举个例子:
>>> def print_everything(*args):
for count, thing in enumerate(args):
… print ‘{0}. {1}’.format(count, thing)
…
>>> print_everthing(‘apple’, ‘banana’, ‘cabbage’)
0. apple
1. banana
2. cabbage
类似的,`**kwargs`允许你处理那些你没有预先定义好的已命名参数
>>> def table_everything(*kwargs):
for name, value in kwargs.items():
… print ‘{0} = {1}’.format(name, value)
…
>>> table_everthing(apple = ‘fruit’, cabbage = ‘vegetable’)
cabbage = vegetable
apple = fruit
你一样可以使用这些命名参数。明确的参数会优先获得值,剩下的都会传递给`*args`和`**kwargs`,命名参数排在参数列表前面,举个例子:
def table_things(titlestring, **kwargs)
你可以同时使用它们,但是`*args`必须出现在`**kwargs`之前。
调用一个函数时也可以用`*`和`**`语法,举个例子:
>>> def print_three_things(*args):
… print ‘a = {0}, b = {1}, c = {2}’.format(a, b , c)
…
>>> mylist = [‘aardvark’, ‘baboon’, ‘cat’]
>>> print_three_things(*mylist)
a = aardvark, b = baboon, c = cat
正如你看到的,它得到了一个list或者tuple,并解包这个list。通过这种方法,它将这些元素和函数中的参数匹配。当然,你可以同时在函数的定义和调用时使用`*`。
### 在Python中,如何干净、pythonic的实现一个复合构造函数
问题[链接](http://stackoverflow.com/questions/682504/what-is-a-clean-pythonic-way-to-have-multiple-constructors-in-python)
实际上 `None`比“魔法”值好多了:
class Cheese():
def __init__(self, num_holes = None):
if (num_holes is None):
…
现在如果你想完全自由地添加更多参数:
class Cheese():
def __init__(self, *args, **kwargs):
#args -- tuple of anonymous arguments
#kwargs -- dictionary of named arguments
self.num_holes = kwargs.get('num_holes',random_holes())
为了更好的解释`*args`和`**kwargs`的概念(实际上你可以修改它们的名字):
def f(*args, **kwargs):
print 'args: ', args, ' kwargs: ', kwargs
>>> f('a')
args: ('a',) kwargs: {}
>>> f(ar='a')
args: () kwargs: {'ar': 'a'}
>>> f(1,2,param=3)
args: (1, 2) kwargs: {'param': 3}
[http://docs.python.org/reference/expressions.html#calls](http://docs.python.org/reference/expressions.html#calls)
### Python参数中,\*\*和\*是干什么的
问题[链接](http://stackoverflow.com/questions/36901/what-does-double-star-and-star-do-for-python-parameters)
`*args`和`**args`是一种惯用的方法,允许不定数量的参数传入函数,在Python文档中有描述[more on defining functions](https://docs.python.org/dev/tutorial/controlflow.html#more-on-defining-functions)
`*args`会把所有的参数当做一个列表传递:
In [1]: def foo(*args):
...: for a in args:
...: print a
...:
...:
In [2]: foo(1)
1
In [4]: foo(1,2,3)
1
2
3
`**kwargs`会把除了那些符合形参的参数作为一个字典传递:
In [5]: def bar(**kwargs):
...: for a in kwargs:
...: print a, kwargs[a]
...:
...:
In [6]: bar(name="one", age=27)
age 27
name one
这两种用法都可以混合进普通参数,允许传入一组固定的的和可变的参数:
def foo(kind, *args, **kwargs):
pass
另一种\*的用法就是在调用一个函数的时候解包参数列表
In [9]: def foo(bar, lee):
...: print bar, lee
...:
...:
In [10]: l = [1,2]
In [11]: foo(*l)
1 2
在Python 3中,可以把\*用在一个待赋值对象的左边([Extended Iterable Upacking](https://www.python.org/dev/peps/pep-3132/)):
first, *rest = [1, 2, 3, 4]
first, *l, last = [1, 2, 3, 4]
### 为什么在Python的函数中,代码运行速度更快
问题[链接](http://stackoverflow.com/questions/11241523/why-does-python-code-run-faster-in-a-function)
你可能要问为什么在存储在本地变量的比全局变量运行速度更快。这是一个CPython执行细节。
记住Cpython在解释器运行时,是编译成字节编码的。当一个函数编译完成,本地变量就全部被存储在一个固定长度的数组中了(而不是字典)而且名字被指定了索引。这是合理的,因为你不能自动添加本地变量到你的函数中去。在指针中循环检索一个本地变量加入到列表中,并且计算琐碎的`PyObject`的增加。
不同的是全局查找(`LOAD_GLOBAL`),是一个涉及哈希查找的字典等等。顺带的,这就是为什么当你需要一个全局变量时,要说明`global i`。如果你曾经在一个范围内给一个变量赋值了,那么编译器会为它的入口发布一些`STORE_FAST`。除非你告诉它不要这样做。
顺便说一句,全局查找仍然是非常棒的。属性查找`foo.bar`是非常慢的。
### 如果把一个变量作为引用传入
问题[链接](http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference)
问题出在[pass by assignment](https://docs.python.org/3/faq/programming.html#how-do-i-write-a-function-with-output-parameters-call-by-reference)。它背后的原理可以分为两部分:
1、 传入的参数实际上是一个对象的引用(但是引用的是值)
2、 有些数据类型是可变的的,有些不是
所以
- 如果你向方法中传递了一个可变的对象,那么方法得到了这些对象的一个引用,只要你开心,就可以随意改变它。但是如果你在方法中重新定义了引用,外部是不知道的,所以当你改变了它,其他的引用仍然指向根对象。
- 如果你向方法中传递了一个不可变对象,那么你不会重新定义外部的引用,你甚至不能改变对象。
我们做一些示例,让它们更清晰。
**列表-一种可变类型**
我们试着去修改传入方法中的列表:
def try_to_change_list_contents(the_list):
print 'got', the_list
the_list.append('four')
print 'changed to', the_list
outer_list = ['one', 'two', 'three']
print 'before, outer_list =', outer_list
try_to_change_list_contents(outer_list)
print 'after, outer_list =', outer_list
输出:
before, outer_list = ['one', 'two', 'three']
got ['one', 'two', 'three']
changed to ['one', 'two', 'three', 'four']
after, outer_list = ['one', 'two', 'three', 'four']
一个参数传入的是`outer_list`的一个引用,而不是它的复制,我们可以使用改变列表的方法去改变它,并且把改变反馈给其他的范围。
现在让我们看一下当我们试着改变这个作为参数传入的引用:
def try_to_change_list_reference(the_list):
print 'got', the_list
the_list = ['and', 'we', 'can', 'not', 'lie']
print 'set to', the_list
outer_list = ['we', 'like', 'proper', 'English']
print 'before, outer_list =', outer_list
try_to_change_list_reference(outer_list)
print 'after, outer_list =', outer_list
输出:
before, outer_list = ['we', 'like', 'proper', 'English']
got ['we', 'like', 'proper', 'English']
set to ['and', 'we', 'can', 'not', 'lie']
after, outer_list = ['we', 'like', 'proper', 'English']
`the_list`参数传递的是值,重新定义一个新的列表,对于方法外部的代码,没有任何影响。`the_list`只是`outer_list`的一个引用,我们让`the_list`指向了一个新的列表,但是我们没有办法修改`outer_list`的指向。
**字符串-不可变类型**
它是不可变的,所以我们没有办法改变字符串的内容。
我们试着改变一下引用。
def try_to_change_string_reference(the_string):
print 'got', the_string
the_string = 'In a kingdom by the sea'
print 'set to', the_string
outer_string = 'It was many and many a year ago'
print 'before, outer_string =', outer_string
try_to_change_string_reference(outer_string)
print 'after, outer_string =', outer_string
输出:
before, outer_string = It was many and many a year ago
got It was many and many a year ago
set to In a kingdom by the sea
after, outer_string = It was many and many a year ago
再一次,`the_string`参数通过值传递,定义一个新的字符串对于外部的代码是不起作用的。`the_string`是`outer_string`的一个引用的复制,我们把`the_string`指向了一个新的字符串。但是我们并没有改变`outer_string`的指向。
我希望这样说可以让事情看上去简单一些了。
编辑:被标记了,这并没有回答@David主要想问的问题。“有没有什么办法让我传入的值是真实的引用?“。回答一下。
**我们怎么避免这些?**
像@Andrea的我回答所展示的,你可以返回一个新的值。这不会改变传入的值,但是确实可以让你得到你想要输出的信息:
def return_a_whole_new_string(the_string):
new_string = something_to_do_with_the_old_string(the_string)
return new_string
# then you could call it like
my_string = return_a_whole_new_string(my_string)
如果你确实想避免使用一个返回的值,你可以创建一个类承载你的值,并把他传入一个函数或者用一个已知的类,像列表一样:
def use_a_wrapper_to_simulate_pass_by_reference(stuff_to_change):
new_string = something_to_do_with_the_old_string(stuff_to_change[0])
stuff_to_change[0] = new_string
# then you could call it like
wrapper = [my_string]
use_a_wrapper_to_simulate_pass_by_reference(wrapper)
do_something_with(wrapper[0])
虽然这样看起来有些笨重。
================================================
FILE: contents/qa-list.md
================================================
### 序列的切片操作
问题 [链接](http://stackoverflow.com/questions/509211/the-python-slice-notation)
It's pretty simple really:
很简单:
a[start:end] # start 到 end-1
a[start:] # start 到 末尾
a[:end] # 0 到 end-1
a[:] # 整个列表的拷贝
还有一个step变量,控制步长,可在上面语法中使用
a[start:end:step] # start through not past end, by step
注意,左闭右开
其他特点,开始或结束下标可能是负数,表示从序列末尾开始计算而非从头开始计算,所以
a[-1] # 最后一个元素
a[-2:] # 最后两个元素
a[:-2] # 除了最后两个元素
Python对程序员很友好,如果序列中存在的元素数量少于你要的,例如,你请求 a[:-2] 但是a只有一个元素,你会得到一个空列表,而不是一个错误.有时候你或许希望返回的是一个错误,所以你必须知道这点
### 判断一个列表为空得最佳实践
问题 [链接](http://stackoverflow.com/questions/53513/python-what-is-the-best-way-to-check-if-a-list-is-empty)
答案:
if not a:
print "List is empty"
#不要用len(a)来判断
### 如何合并两个列表
问题 [链接](http://stackoverflow.com/questions/1720421/merge-two-lists-in-python)
listone = [1,2,3]
listtwo = [4,5,6]
#outcome we expect: mergedlist == [1, 2, 3, 4, 5, 6]
1.不考虑顺序(原来问题不是很明确)
listone + listtwo
#linstone.extend(listtwo)也行,就是会修改listone
2.考虑顺序做些处理
>>> listone = [1,2,3]
>>> listtwo = [4,5,6]
>>> import itertools
>>> for item in itertools.chain(listone, listtwo):
... print item
...
1
2
3
4
5
6
### 如何获取一个列表的长度
问题 [链接](http://stackoverflow.com/questions/518021/getting-the-length-of-an-array-in-python)
python中是不是只有这种方法可以获取长度?语法很奇怪
arr.__len__()
应该使用这种方式
mylist = [1,2,3,4,5]
len(mylist)
这样做法,不需要对每个容器都定义一个.length()方法,你可以使用len()检查所有实现了__len__()方法的对象
### Python中如何复制一个列表
问题 [链接](http://stackoverflow.com/questions/2612802/how-to-clone-a-list-in-python)
可以用切片的方法
new_list = old_list[:]
可以使用list()函数
new_list = list(old_list)
可以使用copy.copy(),比list()稍慢,因为它首先去查询old_list的数据类型
import copy
new_list = copy.copy(old_list)
如果列表中包含对象,可以使用copy.deepcopy(), 所有方法中最慢,但有时候无法避免
import copy
new_list = copy.deepcopy(old_list)
例子:
import copy
class Foo(object):
def __init__(self, val):
self.val = val
def __repr__(self):
return str(self.val)
foo = Foo(1)
a = ['foo', foo]
b = a[:]
c = list(a)
d = copy.copy(a)
e = copy.deepcopy(a)
# edit orignal list and instance
a.append('baz')
foo.val = 5
print "original: %r\n slice: %r\n list(): %r\n copy: %r\n deepcopy: %r" \
% (a, b, c, d, e)
结果:
original: ['foo', 5, 'baz']
slice: ['foo', 5]
list(): ['foo', 5]
copy: ['foo', 5]
deepcopy: ['foo', 1]
效率简单比较
10.59 - copy.deepcopy(old_list)
10.16 - pure python Copy() method copying classes with deepcopy
1.488 - pure python Copy() method not copying classes (only dicts/lists/tuples)
0.325 - for item in old_list: new_list.append(item)
0.217 - [i for i in old_list] (a list comprehension)
0.186 - copy.copy(old_list)
0.075 - list(old_list)
0.053 - new_list = []; new_list.extend(old_list)
0.039 - old_list[:] (list slicing)
### 列表的append和extend的区别
问题 [链接](http://stackoverflow.com/questions/252703/python-append-vs-extend)
>>> x = [1, 2]
>>> x.append(3)
>>> x
[1, 2, 3]
>>> x.append([4,5])
>>> x
[1, 2, 3, [4, 5]]
>>>
>>> x = [1, 2, 3]
>>> x.extend([4, 5])
>>> x
[1, 2, 3, 4, 5]
### 如何随机地从列表中抽取变量
问题 [链接](http://stackoverflow.com/questions/306400/how-do-i-randomly-select-an-item-from-a-list-using-python)
foo = ['a', 'b', 'c', 'd', 'e']
from random import choice
print choice(foo)
### 如何利用下标从列表中删除一个元素
问题 [链接](http://stackoverflow.com/questions/627435/how-to-remove-an-element-from-a-list-by-index-in-python)
1.del
In [9]: a = range(10)
In [10]: a
Out[10]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [11]: del a[-1]
In [12]: a
Out[12]: [0, 1, 2, 3, 4, 5, 6, 7, 8]
2.pop
a = ['a', 'b', 'c', 'd']
a.pop(1)
# now a is ['a', 'c', 'd']
a = ['a', 'b', 'c', 'd']
a.pop()
# now a is ['a', 'b', 'c']
### 获取列表的最后一个元素
问题 [链接](http://stackoverflow.com/questions/930397/how-to-get-the-last-element-of-a-list)
囧
result = l[-1]
result = l.pop()
### 如何将一个列表切分成若干个长度相同的子序列
问题 [链接](http://stackoverflow.com/questions/312443/how-do-you-split-a-list-into-evenly-sized-chunks-in-python)
想要得到这样的效果
l = range(1, 1000)
print chunks(l, 10) -> [ [ 1..10 ], [ 11..20 ], .., [ 991..999 ] ]
使用yield:
def chunks(l, n):
""" Yield successive n-sized chunks from l.
"""
for i in xrange(0, len(l), n):
yield l[i:i+n]
list(chunks(range(10, 75), 10))
直接处理
def chunks(l, n):
return [l[i:i+n] for i in range(0, len(l), n)]
### 如何删除一个list中重复的值同时保证原有顺序
问题 [链接](http://stackoverflow.com/questions/480214/how-do-you-remove-duplicates-from-a-list-in-python-whilst-preserving-order)
我是这么做的额
def uniq(input):
output = []
for x in input:
if x not in output:
output.append(x)
return output
有什么更好的方法?
你可以在这里找到一些可用的方法 [入口](http://www.peterbe.com/plog/uniqifiers-benchmark)
最快的一个
def f7(seq):
seen = set()
seen_add = seen.add
return [ x for x in seq if x not in seen and not seen_add(x)]
为什么要建立一个到`seen.add`函数的引用`seen_add`,而不是直接调用`seen.add()`呢?Python是一个动态语言,如果使用`seen.add()`,迭代器每次都要解析`seen.add()`函数,相比直接调用一个局部变量`seen_add`会消耗更多资源。(评论问,为什么迭代器每次都要解析`seen.add()`)`seen.add()`可能会在每次迭代中可能会发生变化,而Python的Runtime没有智能到发现这一变化,因此安全起见,每次迭代过程中,迭代器都会重新检查这一对象。
如果你需要在同一个数据集中多次是哦那个这个方法,或许你可以使用ordered set处理 http://code.activestate.com/recipes/528878/
插入,删除和归属判断复杂度都是O(1)
### 如何在遍历一个list时删除某些元素
问题 [链接](http://stackoverflow.com/questions/1207406/remove-items-from-a-list-while-iterating-in-python)
使用列表解析
somelist = [x for x in somelist if determine(x)]
上面那个操作将产生一个全新的somelist对象,而失去了对原有somelist对象的引用
#在原有对象上进行修改
somelist[:] = [x for x in somelist if determine(x)]
使用itertools
from itertools import ifilterfalse
somelist[:] = list(ifilterfalse(determine, somelist))
### 如何获取list中包含某个元素所在的下标
问题 [链接](http://stackoverflow.com/questions/176918/in-python-how-do-i-find-the-index-of-an-item-given-a-list-containing-it)
>>> ["foo","bar","baz"].index('bar')
1
参照 [文档](http://docs.python.org/2/tutorial/datastructures.html#more-on-lists)
**注:** 这毫无疑问是最好的答案,但是千万注意.index()返回的是列表中**第一个**符合这个的元素。举个例子 `["foo", "bar", "baz", "bar"].index('bar')`返回的同样是 `1`.
### 如何扁平一个二维数组
问题 [链接](http://stackoverflow.com/questions/952914/making-a-flat-list-out-of-list-of-lists-in-python)
l = [[1,2,3],[4,5,6], [7], [8,9]]
变为[1, 2, 3, 4, 5, 6, 4, 5, 6, 7, 8, 9]
列表解析
[item for sublist in l for item in sublist]
itertools
>>> import itertools
>>> list2d = [[1,2,3],[4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain(*list2d))
# python >= 2.6
>>> import itertools
>>> list2d = [[1,2,3],[4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain.from_iterable(list2d))
sum
sum(l, [])
### 列表解析和map
问题 [链接](http://stackoverflow.com/questions/1247486/python-list-comprehension-vs-map)
更喜欢使用map()而不是列表解析的原因是什么?
在某些情况下,map性能更高一些(当你不是为了某些目的而使用lambda,而是在map和列表解析中使用相同函数).
列表解析在另一些情况下性能更好,并且大多数pythonistas认为这样更简洁直接
使用相同函数,略微优势
$ python -mtimeit -s'xs=range(10)' 'map(hex, xs)'
100000 loops, best of 3: 4.86 usec per loop
$ python -mtimeit -s'xs=range(10)' '[hex(x) for x in xs]'
100000 loops, best of 3: 5.58 usec per loop
相反情况,使用lambda
$ python -mtimeit -s'xs=range(10)' 'map(lambda x: x+2, xs)'
100000 loops, best of 3: 4.24 usec per loop
$ python -mtimeit -s'xs=range(10)' '[x+2 for x in xs]'
100000 loops, best of 3: 2.32 usec per loop
### 列表和元组有什么区别
问题[链接](http://stackoverflow.com/questions/626759/whats-the-difference-between-list-and-tuples)
除了元组是不可变的之外,还有一个语义的区别去控制它们的使用。元组是各种结构类型混杂的(比如,它们的入口有不同的含义),列表则是一致的序列。元组有结构,列表有顺序。
根据这种区别,刻意让代码更为明确和易理解。
用页数和行数来定义一本书中的位置的例子:
my_location = (42, 11) # page number, line number
然后你可以在一个字典里把这个当做键保存位置的记录。然而列表可以用来存储多点定位。通常会想添加或移除一个列表中的某个定位,所以列表是可变的。另一方面,为了保持行数的完好无损,而改变页书的值似乎说不通,这很可能会给你一个新的定位。而且,可能有很完美的解决办法用来处理正确的行数(而不是替换所有的元组)
这一点,有很多有趣的文章,比如[”Python Tuples are Not Just Constant Lists”](http://jtauber.com/blog/2006/04/15/python_tuples_are_not_just_constant_lists/) or [“Understanding tuples vs. lists in Python”](http://news.e-scribe.com/397)。Python官方文档也提到了[“元组是不可变对象,并且用于包含哪些混杂的序列…”](https://docs.python.org/2/tutorial/datastructures.html#tuples-and-sequences)。
在一个动态类型语言比如haskell,元组通常有不同的类型,并且元组的长度必须是固定的。在列表中值必须是同一种类型,值长度不需要固定。所以区别很明显。
最后,Python中还有一个[nametuple](https://docs.python.org/dev/library/collections.html#collections.namedtuple),合理表示一个元组已经有的结构。这些突出的想法明确了元组是类和实例的一种轻型的替换。
### Python 2.7里[...]是什么?
我在IDLE中输入了这段代码:
p = [1, 2]
p[1:1] = [p]
print p
其输出为:
[1, [...], 2]
这里的`[...]`是什么意思,有趣的是,这似乎是一个无限层次的列表的列表的列表,比如:
p[1][1][1]....
问题[链接](http://stackoverflow.com/questions/17160162/what-is-in-python-2-7)
它意味着你在它的内部创建了一个无限嵌套的不能打印的列表。`p`包含一个包含`p`的`p`...等等。`[...]`就是一种让你知道问题的标记,为了通告信息,它不能被而代表。看一下@6502的答案,那些展示了发生什么的优秀的图片。
现在,关于之后你编辑的三个问题:
* 这个[答案](http://stackoverflow.com/questions/7674685/whats-exactly-happening-in-infinite-nested-lists/7680125#7680125)看上去已经覆盖它了
* Ignacio的[链接](http://www.csse.monash.edu.au/~lloyd/tildeFP/1993ACJ/)描述了一些可能的用法
* 这更像是一种数据结构设计的话题而不是编程语言,所以很不幸,你不能在Python的官方文档找到任何参考
以下是@0562的部分回答:
你创建了一个如下的结构:

这个列表的第一个和最后一个元素指向两个数字(1和2),其中间的元素是指向自己。
================================================
FILE: contents/qa-math.md
================================================
### 在Python中如何展示二进制字面值
问题 [链接](http://stackoverflow.com/questions/1476/how-do-you-express-binary-literals-in-python)
十六进制可以
>>> 0x12AF
4783
>>> 0x100
256
八进制可以
>>> 01267
695
>>> 0100
64
二进制如何表示?
Python 2.5 及更早版本: 可以表示为 int('01010101111',2) 但没有字面量
Python 2.6 beta: 可以使用0b1100111 or 0B1100111 表示
Python 2.6 beta: 也可以使用 0o27 or 0O27 (第二字字符是字母 O)
Python 3.0 beta: 同2.6,但不支持027这种语法
### 如何将一个十六进制字符串转为整数
问题 [链接](http://stackoverflow.com/questions/209513/convert-hex-string-to-int-in-python)
>>> int("a", 16)
10
>>> int("0xa",16)
10
详细 [文档](http://docs.python.org/2/library/sys.html)
### 如何强制使用浮点数除法
问题 [链接](http://stackoverflow.com/questions/1267869/how-can-i-force-division-to-be-floating-point-in-python)
如何强制使除法结果c是浮点数
c = a / b
可以使用__future__
>>> from __future__ import division
>>> a = 4
>>> b = 6
>>> c = a / b
>>> c
0.66666666666666663
或者转换,如果除数或被除数是浮点数,那么结果也是浮点数
c = a / float(b)
### 如何将一个整数转为字符串
问题 [链接](http://stackoverflow.com/questions/961632/converting-integer-to-string-in-python)
回答
>>> str(10)
'10'
>>> int('10')
10
对应文档 [int()](http://docs.python.org/2/library/functions.html#int) [str()](http://docs.python.org/2/library/functions.html#str)
### Python的”is”语句在数字类型上表现不正常
问题[链接](http://stackoverflow.com/questions/306313/pythons-is-operator-behaves-unexpectedly-with-integers)
看看这个:
>>> a = 256
>>> b = 256
>>> id(a)
9987148
>>> id(b)
9987148
>>> a = 257
>>> b = 257
>>> id(a)
11662816
>>> id(b)
11662828
编辑:这是我在Python文档中发现的,[7.2.1, “Plain Integer Objects”](https://docs.python.org/2/c-api/int.html):
正在执行的程序会保持一组从-5到256的数值型对象,当你创建一个在这个范围内的数字,你实际上得到了一个已存在的对象的反馈。所以改变1的数值是有可能的,我猜因此这种表现在Python里还定义。
### 将浮点型数字的小数限制为两位
问题[链接](http://stackoverflow.com/questions/455612/limiting-floats-to-two-decimal-points)
你陷入了一个浮点型数据的很老的错误,即所有的数字都不能表示。命令行只能告诉你内存中的全长小数。在浮点里你四舍五入到一个同样的数字。自从计算机是二进制开始,他们把浮点数保存为整数然后除一个2的幂。两位精确的数字有53比特(16位)的精度,常规的浮点数有24比特(8位)的精度。[floating point in python uses double precision](https://docs.python.org/2/tutorial/floatingpoint.html)保存值。
举个例子:
>>>125650429603636838/(2**53)
13.949999999999999
>>> 234042163/(2**24)
13.949999988079071
>>> a=13.946
>>> print(a)
13.946
>>> print("%.2f" % a)
13.95
>>> round(a,2)
13.949999999999999
>>> print("%.2f" % round(a,2))
13.95
>>> print("{0:.2f}".format(a))
13.95
>>> print("{0:.2f}".format(round(a,2)))
13.95
>>> print("{0:.15f}".format(round(a,2)))
13.949999999999999
作为货币如果你只需要小数点后两位的位置,那么你有一对比较好的选择,用整数存储值为分而不是元,之后除以100来得到元。或者用修正过的小数,比如[decimal](https://docs.python.org/2/library/decimal.html)
### 在Python中如何表示逻辑的异或
问题[链接](http://stackoverflow.com/questions/432842/how-do-you-get-the-logical-xor-of-two-variables-in-python)
如果你已经将输入值设为布尔型,那么 != 就是异或。
bool(a) != bool(b)
### 列出小于N的所有质数的最快方法
问题[链接](http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n)
警告:`timeit`可能会根据硬件或Python的版本而产生不同的结果。
下面的脚本对比了执行一个数字的时间:
• ambi_sieve_plain,
• rwh_primes,
• rwh_primes1,
• rwh_primes2,
• sieveOfAtkin,
• sieveOfEratosthenes,
• sundaram3,
• sieve_wheel_30,
• ambi_sieve (requires numpy)
• primesfrom3to (requires numpy)
• primesfrom2to (requires numpy)
感谢stephen,他的sieve_wheel_30引起了我的注意。请相信Robert Wolliam Hanks的primesfrom2to, primesfrom3to, rwh_primes, rwh_primes1,还有rwh_primes2。
通过psyco,在n=1000000的情况下,平行地对比这些Python方法,rwh_primes1是最快的。
+---------------------+-------+
| Method | ms |
+---------------------+-------+
| rwh_primes1 | 43.0 |
| sieveOfAtkin | 46.4 |
| rwh_primes | 57.4 |
| sieve_wheel_30 | 63.0 |
| rwh_primes2 | 67.8 |
| sieveOfEratosthenes | 147.0 |
| ambi_sieve_plain | 152.0 |
| sundaram3 | 194.0 |
+---------------------+-------+
不使用psyco,在n=1000000的情况下,rwh_primes2最快。
+---------------------+-------+
| Method | ms |
+---------------------+-------+
| rwh_primes2 | 68.1 |
| rwh_primes1 | 93.7 |
| rwh_primes | 94.6 |
| sieve_wheel_30 | 97.4 |
| sieveOfEratosthenes | 178.0 |
| ambi_sieve_plain | 286.0 |
| sieveOfAtkin | 314.0 |
| sundaram3 | 416.0 |
+---------------------+-------+
对于所有的方法,如果允许*numpy*,n=1000000,primesfrom2to是最快的。
+---------------------+-------+
| Method | ms |
+---------------------+-------+
| primesfrom2to | 15.9 |
| primesfrom3to | 18.4 |
| ambi_sieve | 29.3 |
+---------------------+-------+
计时器用的是命令:
python -mtimeit -s"import primes" "primes.{method}(10000000)"
`method`替换成不同的方法名字。
primes.py:
#!/usr/bin/env python
import psyco; psyco.full()
from math import sqrt, ceil
import numpy as np
def rwh_primes(n):
# http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
""" Returns a list of primes < n """
sieve = [True] * n
for i in xrange(3,int(n**0.5)+1,2):
if sieve[i]:
sieve[i*i::2*i]=[False]*((n-i*i-1)/(2*i)+1)
return [2] + [i for i in xrange(3,n,2) if sieve[i]]
def rwh_primes1(n):
# http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
""" Returns a list of primes < n """
sieve = [True] * (n/2)
for i in xrange(3,int(n**0.5)+1,2):
if sieve[i/2]:
sieve[i*i/2::i] = [False] * ((n-i*i-1)/(2*i)+1)
return [2] + [2*i+1 for i in xrange(1,n/2) if sieve[i]]
def rwh_primes2(n):
# http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
""" Input n>=6, Returns a list of primes, 2 <= p < n """
correction = (n%6>1)
n = {0:n,1:n-1,2:n+4,3:n+3,4:n+2,5:n+1}[n%6]
sieve = [True] * (n/3)
sieve[0] = False
for i in xrange(int(n**0.5)/3+1):
if sieve[i]:
k=3*i+1|1
sieve[ ((k*k)/3) ::2*k]=[False]*((n/6-(k*k)/6-1)/k+1)
sieve[(k*k+4*k-2*k*(i&1))/3::2*k]=[False]*((n/6-(k*k+4*k-2*k*(i&1))/6-1)/k+1)
return [2,3] + [3*i+1|1 for i in xrange(1,n/3-correction) if sieve[i]]
def sieve_wheel_30(N):
# http://zerovolt.com/?p=88
''' Returns a list of primes <= N using wheel criterion 2*3*5 = 30
Copyright 2009 by zerovolt.com
This code is free for non-commercial purposes, in which case you can just leave this comment as a credit for my work.
If you need this code for commercial purposes, please contact me by sending an email to: info [at] zerovolt [dot] com.'''
__smallp = ( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59,
61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139,
149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311,
313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401,
409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491,
499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599,
601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683,
691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797,
809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887,
907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997)
wheel = (2, 3, 5)
const = 30
if N < 2:
return []
if N <= const:
pos = 0
while __smallp[pos] <= N:
pos += 1
return list(__smallp[:pos])
# make the offsets list
offsets = (7, 11, 13, 17, 19, 23, 29, 1)
# prepare the list
p = [2, 3, 5]
dim = 2 + N // const
tk1 = [True] * dim
tk7 = [True] * dim
tk11 = [True] * dim
tk13 = [True] * dim
tk17 = [True] * dim
tk19 = [True] * dim
tk23 = [True] * dim
tk29 = [True] * dim
tk1[0] = False
# help dictionary d
# d[a , b] = c ==> if I want to find the smallest useful multiple of (30*pos)+a
# on tkc, then I need the index given by the product of [(30*pos)+a][(30*pos)+b]
# in general. If b < a, I need [(30*pos)+a][(30*(pos+1))+b]
d = {}
for x in offsets:
for y in offsets:
res = (x*y) % const
if res in offsets:
d[(x, res)] = y
# another help dictionary: gives tkx calling tmptk[x]
tmptk = {1:tk1, 7:tk7, 11:tk11, 13:tk13, 17:tk17, 19:tk19, 23:tk23, 29:tk29}
pos, prime, lastadded, stop = 0, 0, 0, int(ceil(sqrt(N)))
# inner functions definition
def del_mult(tk, start, step):
for k in xrange(start, len(tk), step):
tk[k] = False
# end of inner functions definition
cpos = const * pos
while prime < stop:
# 30k + 7
if tk7[pos]:
prime = cpos + 7
p.append(prime)
lastadded = 7
for off in offsets:
tmp = d[(7, off)]
start = (pos + prime) if off == 7 else (prime * (const * (pos + 1 if tmp < 7 else 0) + tmp) )//const
del_mult(tmptk[off], start, prime)
# 30k + 11
if tk11[pos]:
prime = cpos + 11
p.append(prime)
lastadded = 11
for off in offsets:
tmp = d[(11, off)]
start = (pos + prime) if off == 11 else (prime * (const * (pos + 1 if tmp < 11 else 0) + tmp) )//const
del_mult(tmptk[off], start, prime)
# 30k + 13
if tk13[pos]:
prime = cpos + 13
p.append(prime)
lastadded = 13
for off in offsets:
tmp = d[(13, off)]
start = (pos + prime) if off == 13 else (prime * (const * (pos + 1 if tmp < 13 else 0) + tmp) )//const
del_mult(tmptk[off], start, prime)
# 30k + 17
if tk17[pos]:
prime = cpos + 17
p.append(prime)
lastadded = 17
for off in offsets:
tmp = d[(17, off)]
start = (pos + prime) if off == 17 else (prime * (const * (pos + 1 if tmp < 17 else 0) + tmp) )//const
del_mult(tmptk[off], start, prime)
# 30k + 19
if tk19[pos]:
prime = cpos + 19
p.append(prime)
lastadded = 19
for off in offsets:
tmp = d[(19, off)]
start = (pos + prime) if off == 19 else (prime * (const * (pos + 1 if tmp < 19 else 0) + tmp) )//const
del_mult(tmptk[off], start, prime)
# 30k + 23
if tk23[pos]:
prime = cpos + 23
p.append(prime)
lastadded = 23
for off in offsets:
tmp = d[(23, off)]
start = (pos + prime) if off == 23 else (prime * (const * (pos + 1 if tmp < 23 else 0) + tmp) )//const
del_mult(tmptk[off], start, prime)
# 30k + 29
if tk29[pos]:
prime = cpos + 29
p.append(prime)
lastadded = 29
for off in offsets:
tmp = d[(29, off)]
start = (pos + prime) if off == 29 else (prime * (const * (pos + 1 if tmp < 29 else 0) + tmp) )//const
del_mult(tmptk[off], start, prime)
# now we go back to top tk1, so we need to increase pos by 1
pos += 1
cpos = const * pos
# 30k + 1
if tk1[pos]:
prime = cpos + 1
p.append(prime)
lastadded = 1
for off in offsets:
tmp = d[(1, off)]
start = (pos + prime) if off == 1 else (prime * (const * pos + tmp) )//const
del_mult(tmptk[off], start, prime)
# time to add remaining primes
# if lastadded == 1, remove last element and start adding them from tk1
# this way we don't need an "if" within the last while
if lastadded == 1:
p.pop()
# now complete for every other possible prime
while pos < len(tk1):
cpos = const * pos
if tk1[pos]: p.append(cpos + 1)
if tk7[pos]: p.append(cpos + 7)
if tk11[pos]: p.append(cpos + 11)
if tk13[pos]: p.append(cpos + 13)
if tk17[pos]: p.append(cpos + 17)
if tk19[pos]: p.append(cpos + 19)
if tk23[pos]: p.append(cpos + 23)
if tk29[pos]: p.append(cpos + 29)
pos += 1
# remove exceeding if present
pos = len(p) - 1
while p[pos] > N:
pos -= 1
if pos < len(p) - 1:
del p[pos+1:]
# return p list
return p
def sieveOfEratosthenes(n):
"""sieveOfEratosthenes(n): return the list of the primes < n."""
# Code from: <dickinsm@gmail.com>, Nov 30 2006
# http://groups.google.com/group/comp.lang.python/msg/f1f10ced88c68c2d
if n <= 2:
return []
sieve = range(3, n, 2)
top = len(sieve)
for si in sieve:
if si:
bottom = (si*si - 3) // 2
if bottom >= top:
break
sieve[bottom::si] = [0] * -((bottom - top) // si)
return [2] + [el for el in sieve if el]
def sieveOfAtkin(end):
"""sieveOfAtkin(end): return a list of all the prime numbers <end
using the Sieve of Atkin."""
# Code by Steve Krenzel, <Sgk284@gmail.com>, improved
# Code: http://krenzel.info/?p=83
# Info: http://en.wikipedia.org/wiki/Sieve_of_Atkin
assert end > 0
lng = ((end-1) // 2)
sieve = [False] * (lng + 1)
x_max, x2, xd = int(sqrt((end-1)/4.0)), 0, 4
for xd in xrange(4, 8*x_max + 2, 8):
x2 += xd
y_max = int(sqrt(end-x2))
n, n_diff = x2 + y_max*y_max, (y_max << 1) - 1
if not (n & 1):
n -= n_diff
n_diff -= 2
for d in xrange((n_diff - 1) << 1, -1, -8):
m = n % 12
if m == 1 or m == 5:
m = n >> 1
sieve[m] = not sieve[m]
n -= d
x_max, x2, xd = int(sqrt((end-1) / 3.0)), 0, 3
for xd in xrange(3, 6 * x_max + 2, 6):
x2 += xd
y_max = int(sqrt(end-x2))
n, n_diff = x2 + y_max*y_max, (y_max << 1) - 1
if not(n & 1):
n -= n_diff
n_diff -= 2
for d in xrange((n_diff - 1) << 1, -1, -8):
if n % 12 == 7:
m = n >> 1
sieve[m] = not sieve[m]
n -= d
x_max, y_min, x2, xd = int((2 + sqrt(4-8*(1-end)))/4), -1, 0, 3
for x in xrange(1, x_max + 1):
x2 += xd
xd += 6
if x2 >= end: y_min = (((int(ceil(sqrt(x2 - end))) - 1) << 1) - 2) << 1
n, n_diff = ((x*x + x) << 1) - 1, (((x-1) << 1) - 2) << 1
for d in xrange(n_diff, y_min, -8):
if n % 12 == 11:
m = n >> 1
sieve[m] = not sieve[m]
n += d
primes = [2, 3]
if end <= 3:
return primes[:max(0,end-2)]
for n in xrange(5 >> 1, (int(sqrt(end))+1) >> 1):
if sieve[n]:
primes.append((n << 1) + 1)
aux = (n << 1) + 1
aux *= aux
for k in xrange(aux, end, 2 * aux):
sieve[k >> 1] = False
s = int(sqrt(end)) + 1
if s % 2 == 0:
s += 1
primes.extend([i for i in xrange(s, end, 2) if sieve[i >> 1]])
return primes
def ambi_sieve_plain(n):
s = range(3, n, 2)
for m in xrange(3, int(n**0.5)+1, 2):
if s[(m-3)/2]:
for t in xrange((m*m-3)/2,(n>>1)-1,m):
s[t]=0
return [2]+[t for t in s if t>0]
def sundaram3(max_n):
# http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/2073279#2073279
numbers = range(3, max_n+1, 2)
half = (max_n)//2
initial = 4
for step in xrange(3, max_n+1, 2):
for i in xrange(initial, half, step):
numbers[i-1] = 0
initial += 2*(step+1)
if initial > half:
return [2] + filter(None, numbers)
################################################################################
# Using Numpy:
def ambi_sieve(n):
# http://tommih.blogspot.com/2009/04/fast-prime-number-generator.html
s = np.arange(3, n, 2)
for m in xrange(3, int(n ** 0.5)+1, 2):
if s[(m-3)/2]:
s[(m*m-3)/2::m]=0
return np.r_[2, s[s>0]]
def primesfrom3to(n):
# http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
""" Returns a array of primes, p < n """
assert n>=2
sieve = np.ones(n/2, dtype=np.bool)
for i in xrange(3,int(n**0.5)+1,2):
if sieve[i/2]:
sieve[i*i/2::i] = False
return np.r_[2, 2*np.nonzero(sieve)[0][1::]+1]
def primesfrom2to(n):
# http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
""" Input n>=6, Returns a array of primes, 2 <= p < n """
sieve = np.ones(n/3 + (n%6==2), dtype=np.bool)
sieve[0] = False
for i in xrange(int(n**0.5)/3+1):
if sieve[i]:
k=3*i+1|1
sieve[ ((k*k)/3) ::2*k] = False
sieve[(k*k+4*k-2*k*(i&1))/3::2*k] = False
return np.r_[2,3,((3*np.nonzero(sieve)[0]+1)|1)]
if __name__=='__main__':
import itertools
import sys
def test(f1,f2,num):
print('Testing {f1} and {f2} return same results'.format(
f1=f1.func_name,
f2=f2.func_name))
if not all([a==b for a,b in itertools.izip_longest(f1(num),f2(num))]):
sys.exit("Error: %s(%s) != %s(%s)"%(f1.func_name,num,f2.func_name,num))
n=1000000
test(sieveOfAtkin,sieveOfEratosthenes,n)
test(sieveOfAtkin,ambi_sieve,n)
test(sieveOfAtkin,ambi_sieve_plain,n)
test(sieveOfAtkin,sundaram3,n)
test(sieveOfAtkin,sieve_wheel_30,n)
test(sieveOfAtkin,primesfrom3to,n)
test(sieveOfAtkin,primesfrom2to,n)
test(sieveOfAtkin,rwh_primes,n)
test(sieveOfAtkin,rwh_primes1,n)
test(sieveOfAtkin,rwh_primes2,n)
执行每一种方法都会得到同一个结果。
### 在Python中,自增和自减操作符的表现
问题[链接](http://stackoverflow.com/questions/1485841/behaviour-of-increment-and-decrement-operators-in-python)
`++`不是一个操作符。只是两个`+`操作符, `+`操作符是一个同一性的操作符,什么都做。(解释一下:`+`和`-`作为一元操作符,只对数字起效,但是我假定你不会期望`++`操作符对于字符串也起效)
++count
其实就是
+(+count)
统一翻译为
count
你可以使用稍微长一点的`+=`操作符来实现你的需求:
count += 1
我怀疑`++`和`--`的存在是为了一致性和简单性。我不能确定Guido van Rossum做这个决定的原因,但是我猜测有以下原因:
- 只是简单的解析。严格来说,`++count`是模糊的,因为它是`+`,`+`,`count`(两个一元`+`操作符)简化为`++`和`count`(只是一元的`++`操作符),不是什么严重的语病,但是他确实存在。
- 简单说。`++`只不过是`+= 1`的同义词。它是一个简短的发明,因为C编译器太蠢不能把`a += 1`优化为几乎所有电脑都有的`inc`。这个年代,优化编译器和字节码的解释语言,向语言中添加操作符允许程序员优化他们的代码这种事情通常会引起不满,尤其是像Python这种设计为解释和阅读型的语言。
- 混乱的副作用。在含有`++`的语言中一个常见的新手错误就是混合了它和pre-,post-自增/自减操作符的区别(无论是优先级,还是返回值),而且Python喜欢消除一些语言陷阱。前期增量后期增量的优先级在C语言中表现的非常糟糕,而且难以置信的容易出错。
================================================
FILE: contents/qa-modules.md
================================================
### \_\_init\_\_.py是做什么用的
问题 [链接](http://stackoverflow.com/questions/448271/what-is-init-py-for)
这是包的一部分,[具体文档](http://docs.python.org/2/tutorial/modules.html#packages)
\_\_init\_\_.py让Python把目录当成包,
最简单的例子,\_\_init\_\_.py仅是一个空文件,但它可以一样执行包初始化代码或者设置\_\_all\_\_变量,后续说明
### 如何使用绝对路径import一个模块
问题 [链接](http://stackoverflow.com/questions/67631/how-to-import-a-module-given-the-full-path)
import imp
foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()
### 获取Python模块文件的路径
问题 [链接](http://stackoverflow.com/questions/247770/retrieving-python-module-path)
如何才能获取一个模块其所在的路径
回答
import a_module
print a_module.__file__
获取其所在目录,可以
import os
path = os.path.dirname(amodule.__file__)
### 谁可以解释一下__all__么?
问题 [链接](http://stackoverflow.com/questions/44834/can-someone-explain-all-in-python)
该模块的公有对象列表
__all__指定了使用import module时,哪些对象会被import进来.其他不在列表里的不会被导入
__all__ = ["foo", "bar"]
it's a list of public objects of that module -- it overrides the default of hiding everything that begins with an underscore
### 如何重新加载一个python模块
问题 [链接](http://stackoverflow.com/questions/437589/how-do-i-unload-reload-a-python-module)
使用reload内置函数
reload(module_name)
import foo
while True:
# Do some things.
if is_changed(foo):
foo = reload(foo)
### 在Python中,如何表示Enum(枚举)
问题[链接](http://stackoverflow.com/questions/36932/how-can-i-represent-an-enum-in-python)
Enums已经添加进了Python 3.4,详见PEP435。同时在pypi下被反向移植进了3.3,3.2,3.1,2.7,2.6,2.5和2.4。
通过`$ pip install enum34`来使用向下兼容的Enum,下载`enum`(没有数字)则会安装完全不同并且有冲突的版本。
from enum imoprt Enum
Animal = Enum(‘Animal’, ‘ant bee cat dog’)
等效的:
class Animals(Enum):
ant = 1
bee = 2
cat = 3
dog = 4
在早期的版本中,实现枚举的一种方法是:
def enum(**enums):
return type(‘Enum’, (), enums)
使用起来像这样:
>>> Numbers = enum(ONE=1, TWO=2, THREE='three')
>>> Numbers.ONE
1
>>> Numbers.TWO
2
>>> Numbers.THREE
'three'
也可以轻松的实现自动列举像下面这样:
def enum(*squential, **named):
enums = dict(zip(sequential, range(len(sequential))), **named)
return type(‘Enum’, (), enums)
使用起来像这样:
>>> Numbers = enum('ZERO', 'ONE', 'TWO')
>>> Numbers.ZERO
0
>>> Numbers.ONE
1
支持把值转换为名字,可以这样添加:
def enum(*sequential, **named):
enums = dict(zip(sequential, range(len(sequential))), **named)
reverse = dict((value, key) for key, value in enums.iteritems())
enums['reverse_mapping'] = reverse
return type('Enum', (), enums)
这将会根据名字重写任何东西,但是对于渲染你打印出的枚举值很有效。如果反向映射不存在,它会抛出KeyError。看一个例子:
>>> Numbers.reverse_mapping[‘three’]
’THREE’
### if __name__ == “__main__”做了什么?
问题[链接](http://stackoverflow.com/questions/419163/what-does-if-name-main-do)
稍微拓展一下Harley的答案...
当Python的解释器读一个源文件时,它执行了里面能找到的所有代码。在执行之前,它会定义少数几个变量。举个例子,如果Python解释器把该模块(即源文件)当做主程序运行,它就会把特殊的`__name__`变量的值设置为`“__main__”`。如果这个文件被其他模块引用,`__name__`就会被设置为其他模块的名字。
就你的脚本来说,我们假设把它当做主函数来执行,你可能会在命令行上这样用:
python threading_example.py
设置好特殊变量之后,它会执行`import`声明并加载其他的模块。然后它会预估`def`的缩进,创建一个函数对象和一个指向函数对象的值叫做`myfunction`。之后它将读取`if`语句,确定`__name__`等于`”__main__”`后,执行缩进并展示。
这样做的主要原因是,有时候你写了一个可以直接执行的模块(一个`.py`文件),同时,它也可以被其他模块引用。通过执行主函数检查,你可以让你的代码只在作为主程序时执行,而在被其他模块引用或调用其中的函数时不执行。
[这页](http://ibiblio.org/g2swap/byteofpython/read/module-name.html)可以看到更多的细节。
### 通过相对路径引用一个模块
问题[链接](http://stackoverflow.com/questions/279237/import-a-module-from-a-relative-path)
假设你的两个文件夹都是真实的python包(都有`__init__.py`文件在里面),这里有一个可以安全的把相对路径模块包含进本地的脚本。
我假设你想这样做,因为你需要在脚本中包含一系列的模块。我在许多产品的生产环境和不同的情景下用过这个:调用其他文件夹下的脚本或者在不打开一个新的解释器的情况下在Python中执行。
import os, sys, inspect
# realpath() will make your script run, even if you symlink it :)
cmd_folder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]))
if cmd_folder not in sys.path:
sys.path.insert(0, cmd_folder)
# use this if you want to include modules from a subfolder
cmd_subfolder=os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"subfolder")))
if cmd_subfolder not in sys.path:
sys.path.insert(0, cmd_subfolder)
# Info:
# cmd_folder = os.path.dirname(os.path.abspath(__file__)) # DO NOT USE__file__ !!!
# __file__ fails if script is called in different ways on Windows
# __file__ fails if someone does os.chdir() before
# sys.argv[0] also fails because it doesn't not always contains the path
通过这个途径,确实迫使Python使用你的模块,而不用系统自带的那些。
但是注意。在`egg`文件中的模块会发生什么我确实不知道。可能会失败。如果你知道更好的解决办法请留言,我会花几个小时去改进它。
### Python中如何进行间接引用
问题[链接](http://stackoverflow.com/questions/72852/how-to-do-relative-imports-in-python)
看上去每个人都希望告诉你你该怎么做好过只回答这个问题。
问题在于你在运行一个作为`’__main__’`的模块,向解释器传递mod1.py作为一个参数。
来自[PEP 328](http://stackoverflow.com/questions/72852/how-to-do-relative-imports-in-python):
Relative imports use a module's __name__ attribute to determine that module's position in the package hierarchy. If the module's name does not contain any package information (e.g. it is set to '__main__') then relative imports are resolved as if the module were a top level module, regardless of where the module is actually located on the file system.
在Python 2.6中,他们添加了为主模块表现模块关系的功能,[PEP 366](https://www.python.org/dev/peps/pep-0366/)描述了这个功能。
================================================
FILE: contents/qa-oop.md
================================================
### Python 'self' 解释
问题 [链接](http://stackoverflow.com/questions/2709821/python-self-explained)
self关键字的作用是什么?
我理解他用户在创建class时具体化实例,但我无法理解为何需要给每个方法加入self作为参数.
举例,在ruby中,我这么做:
class myClass
def myFunc(name)
@name = name
end
end
我可以很好地理解,非常简单.但是在Python中,我需要去加入self:
class myClass:
def myFunc(self, name):
self.name = name
有谁能解释下么?
使用self关键字的原因是,Python没有@语法用于引用实例属性.Python决定用一种方式声明方法:实例对象自动传递给属于它的方法,但不是接收自动化:方法的第一个参数是调用这个方法的实例对象本身.这使得方法整个同函数一致,并且由你自己决定真实的名(虽然self是约定,但当你使用其他名的时候,通常人们并不乐意接受).self对于代码不是特殊的,只是另一个对象.
Python本来可以做一些用来区分真实的名字和属性的区别 —— 像Ruby有的特殊语法,或者像C++/Java的命令声明,或者其他可能的的语法 —— 但是Python没有这么做.Python致力于使事情变得明确简单,让事情是其本身,虽然并不是全部地方都这么做,但是实例属性是这么做的!这就是为什么给一个实例属性赋值时需要知道是给哪个实例赋值,并且,这就是为什么需要self
举例
class Vector(object):
def __init__(self, x, y):
self.x = x
self.y = y
def length(self):
return math.sqrt(self.x ** 2 + self.y ** 2)
等价于
def length_global(vector):
return math.sqrt(vector.x ** 2 + vector.y ** 2)
另外
v_instance.length()
转为
Vector.length(v_instance)
### 为什么Python的'private'方法并不是真正的私有方法
问题 [链接](http://stackoverflow.com/questions/70528/why-are-pythons-private-methods-not-actually-private)
Python允许我们创建'private' 函数:变量以两个下划线开头,像这样: *__myPrivateMethod()*.
但是,如何解释:
>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
>>> obj.myPublicMethod()
public method
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "", line 1, in
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
>>> obj._MyClass__myPrivateMethod()
this is private!!
dir(obj) 和 obj._MyClass__myPrivateMethod()
回答
‘private'只是用作,确保子类不会意外覆写父类的私有方法和属性.不是为了保护外部意外访问而设计的!
例如:
>>> class Foo(object):
... def __init__(self):
... self.__baz = 42
... def foo(self):
... print self.__baz
...
>>> class Bar(Foo):
... def __init__(self):
... super(Bar, self).__init__()
... self.__baz = 21
... def bar(self):
... print self.__baz
...
>>> x = Bar()
>>> x.foo()
42
>>> x.bar()
21
>>> print x.__dict__
{'_Bar__baz': 21, '_Foo__baz': 42}
当然,这对于两个同名的类没有作用
另外,可以查看diveintopython的解释 [入口](http://www.faqs.org/docs/diveintopython/fileinfo_private.html#d0e11521)
### Python中类方法的作用是什么
问题 [链接](http://stackoverflow.com/questions/38238/what-are-class-methods-in-python-for)
我现在意识到,我不需要像我在使用java的static方法那样使用类方法,但是我不确定什么时候使用
谁能通过一个好的例子解释下Python中的类方法,至少有人能告诉我什么时候确实需要使用类方法
类方法用在:当你需要使用不属于任何明确实例的方法,但同时必须涉及类.有趣的是,你可以在子类中覆写,这在Java的static方法和Python的模块级别函数中是不可能做到的
如果你有一个MyClass, 并且一个模块级别函数操作MyClass(工厂,依赖注入桩等等), 声明一个类方法.然后这个类方法可以在子类中调用
### Python中 __new__ 和 __init__的用法
问题 [链接](http://stackoverflow.com/questions/674304/pythons-use-of-new-and-init)
我很疑惑,为何__init__总是在__new__之后调用
如下
class A(object):
_dict = dict()
def __new__(cls):
if 'key' in A._dict:
print "EXISTS"
return A._dict['key']
else:
print "NEW"
return super(A, cls).__new__(cls)
def __init__(self):
print "INIT"
A._dict['key'] = self
print ""
a1 = A()
a2 = A()
a3 = A()
输出
NEW
INIT
EXISTS
INIT
EXISTS
INIT
有木有人可以解释一下
来自 [链接](http://mail.python.org/pipermail/tutor/2008-April/061426.html)
使用__new__,当你需要控制一个实例的生成
使用__init__,当你需要控制一个实例的初始化
__new__是实例创建的第一步.最先被调用,并且负责返回类的一个新实例.
相反的,__init__不返回任何东西,只是负责在实例创建后进行初始化
通常情况下,你不必重写__new__除非你写一个子类继承不可变类型,例如str,int,unicode或tuple
你必须了解到,你尝试去做的用[Factory](http://en.wikipedia.org/wiki/Factory_object)可以很好地解决,并且是最好的解决方式.使用__new__不是一个简洁的处理方式,一个[factory例子](http://code.activestate.com/recipes/86900/)
### 如何获取一个实例的类名
问题 [链接](http://stackoverflow.com/questions/510972/getting-the-class-name-of-an-instance-in-python)
x.__class__.__name__
### @staticmethod和@classmethod的区别
问题 [链接](http://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python)
staticmethod,静态方法在调用时,对类及实例一无所知
仅仅是获取传递过来的参数,没有隐含的第一个参数,在Python里基本上用处不大,你完全可以用一个模块函数替换它
classmethod, 在调用时,将会获取到其所在的类,或者类实例,作为其第一个参数
当你想将函数作为一个类工厂时,这非常有用: 第一个参数是类,你可以实例化出对应实例对象,甚至子类对象。
可以观察下 dict.fromkey(),是一个类方法,当子类调用时,返回子类的实例
>>> class DictSubclass(dict):
... def __repr__(self):
... return "DictSubclass"
...
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>>
### 如何定义静态方法(static method)
问题 [链接](http://stackoverflow.com/questions/735975/static-methods-in-python)
使用 [staticmethod](http://docs.python.org/2/library/functions.html#staticmethod)装饰器
class MyClass(object):
@staticmethod
def the_static_method(x):
print x
MyClass.the_static_method(2) # outputs 2
### Python中的类变量(环境变量)
问题 [链接](http://stackoverflow.com/questions/68645/static-class-variables-in-python)
在类中定义的变量,不在方法定义中,成为类变量或静态变量
>>> class MyClass:
... i = 3
...
>>> MyClass.i
3
i是类级别的变量,但这里要和实例级别的变量i区分开
>>> m = MyClass()
>>> m.i = 4
>>> MyClass.i, m.i
>>> (3, 4)
这和C++/java完全不同,但和C#区别不大,C#不允许类实例获取静态变量
具体见 [what the Python tutorial has to say on the subject of classes and class objects](http://docs.python.org/2/tutorial/classes.html#SECTION0011320000000000000000)
另外,静态方法
class C:
@staticmethod
def f(arg1, arg2, ...): ...
### 如何判断一个对象是否拥有某个属性
问题 [链接](http://stackoverflow.com/questions/610883/how-to-know-if-an-object-has-an-attribute-in-python)
if hasattr(a, 'property'):
a.property
两种风格
EAFP(easier to ask for forgiveness than permission)
LBYL(look before you leap)
相关内容
[EAFP vs LBYL (was Re: A little disappointed so far)](http://web.archive.org/web/20070929122422/http://mail.python.org/pipermail/python-list/2003-May/205182.html)
[EAFP vs. LBYL @Code Like a Pythonista: Idiomatic Python](http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#eafp-vs-lbyl)
try:
doStuff(a.property)
except AttributeError:
otherStuff()
or
if hasattr(a, 'property'):
doStuff(a.property)
else:
otherStuff()
### Python中有没有简单优雅的方式定义单例类
问题 [链接](http://stackoverflow.com/questions/31875/is-there-a-simple-elegant-way-to-define-singletons-in-python)
我不认为有必要,一个拥有函数的模块(不是类)可以作为很好的单例使用,它的所有变量被绑定到这个模块,无论如何都不能被重复实例化
如果你确实想用一个类来实现,在python中不能创建私有类或私有构造函数,所以你不能隔离多个实例而仅仅通过自己的API来访问属性
我还是认为将函数放入模块,并将其作为一个单例来使用是最好的办法
### 理解Python的Super()和init方法
问题 [链接](http://stackoverflow.com/questions/576169/understanding-python-super-and-init-methods)
尝试着去理解super().从表面上看,两个子类都能正常创建.我只是好奇他们两者之间的不同点
class Base(object):
def __init__(self):
print "Base created"
class ChildA(Base):
def __init__(self):
Base.__init__(self)
class ChildB(Base):
def __init__(self):
super(ChildB, self).__init__()
print ChildA(),ChildB()
回答
Super让你避免明确地引用基类,这是一点。最大的优势是,当出现多重继承的时候,各种[有趣的情况](http://www.artima.com/weblogs/viewpost.jsp?thread=236275)就会出现。查看super[官方文档](http://docs.python.org/library/functions.html#super).
另外注意,在Python3.0中,可以使用super().__init__() 代替 super(ChildB, self).__init__().IMO略有优势.
### 在Python中,如何判断一个对象iterable?
问题 [链接](http://stackoverflow.com/questions/1952464/in-python-how-do-i-determine-if-an-object-is-iterable)
1. 检查__iter__对序列类型有效,但是对例如string,无效
try:
iterator = iter(theElement)
except TypeError:
# not iterable
else:
# iterable
# for obj in iterator:
# pass
2. 使用collections
import collections
if isinstance(e, collections.Iterable):
# e is iterable
### 构建一个基本的Python迭代器
问题[链接](http://stackoverflow.com/questions/19151/build-a-basic-python-iterator)
在Python中,迭代器对象遵循迭代器协议,这意味着它提供了两种方法: `__iter__()`和`next()`。`__iter__()`返回一个迭代器对象并且在循环开始时就隐式的被调用。`next()`方法返回下一个值,并在循环的每一次增量中被调用。当没有值需要返回时,`next()`引发一个StopIteration异常,这个异常被循环结构隐式的捕获从而停止迭代。
这有一个简单计数例子:
class Counter:
def __init__(self, low, high):
self.current = low
self.high = high
def __iter__(self):
return self
def next(self): # Python 3: def __next__(self)
if self.current > self.high:
raise StopIteration
else:
self.current += 1
return self.current - 1
for c in Counter(3, 8):
print c
上述会打印出:
3
4
5
6
7
8
这个用生成器写会更简单一些,下面是之前答案的翻写:
def counter(low, high):
current = low
while current <= high:
yield current
current += 1
for c in counter(3, 8):
print c
打印出来的内容是一样的。在后台,生成器对象支持迭代器协议,大体上对Counter类做一些同样事情。
[Iterators and Simple Generators](http://www.ibm.com/developerworks/library/l-pycon.html),David Mertz的这篇文章,是一篇对迭代器非常好的介绍。
### 在Python中,抽象类和接口有什么区别?
问题[链接](http://stackoverflow.com/questions/372042/difference-between-abstract-class-and-interface-in-python)
看看下面这个:
class Abstract1(object):
"""Some description that tells you it's abstract,
often listing the methods you're expected to supply."""
def aMethod(self):
raise NotImplementedError( "Should have implemented this" )
因为在Python中没有(也不需要)一个正式的接口协议,类Java的抽象类和接口的区别并不存在。如果有人尝试定义一个正式的接口,它其实也是一个抽象类。唯一的不同就是在文档注释的表述。
并且当你使用鸭子类型时,抽象类和接口的区别有点吹毛求疵了。
Java使用接口是因为它没有多重继承。
因为Python有多重继承,你可能还会看到类似这样的东西:
class SomeAbstraction( object ):
pass # lots of stuff - but missing something
class Mixin1( object ):
def something( self ):
pass # one implementation
class Mixin2( object ):
def something( self ):
pass # another
class Concrete1( SomeAbstraction, Mixin1 ):
pass
class Concrete2( SomeAbstraction, Mixin2 ):
pass
这是一种使用混合抽象超类去创建不相交的具体子类的方法。
### Python 的__slots__
问题[链接](http://stackoverflow.com/questions/472000/python-slots)
引用[Jacob Hallen](http://code.activestate.com/lists/python-list/531365/):
`__slots__`的正确使用方法是保存对象的空间。取代使用允许任何时间给类添加属性的动态字典,有一种在创建之后不允许添加的静态结构。使用slots节省了给所有对象同一个字典的系统开销。有时候这是一个很有效的优化,但它也会变得毫无用处,前提是Python的解释器足够动态化,可以在确实需要为对象增加某些东西时只需要字典。
不幸的是,使用slots有一个副作用。他们通过一种方法改变了那些带有slots的对象的表现形式,使它们被古怪的控制者和细小的静态归类滥用。这很糟糕,因为古怪的控制者应该滥用元类,而细小的静态归类应该滥用生成器。但是从Python开始,只有这一种显著的方法了。
将CPython做的很聪明,聪明到可以不用`__slots__`保存空间,是一个主要的工作,这也就是为什么它不在P3k的更改列表中(到目前为止)。
### Python中,新式类和旧式类的区别
问题[链接](http://stackoverflow.com/questions/54867/what-is-the-difference-between-old-style-and-new-style-classes-in-python)
根据[https://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes](https://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classeshttps://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes):
Up to Python 2.1, old-style classes were the only flavour available to the user. The concept of (old-style) class is unrelated to the concept of type: if x is an instance of an old-style class, then x.__class__ designates the class of x, but type(x) is always <type 'instance'>. This reflects the fact that all old-style instances, independently of their class, are implemented with a single built-in type, called instance.
New-style classes were introduced in Python 2.2 to unify classes and types. A new-style class neither more nor less than a user-defined type. If x is an instance of a new-style class, then type(x) is the same as x.__class__.
The major motivation for introducing new-style classes is to provide a unified object model with a full meta-model. It also has a number of immediate benefits, like the ability to subclass most built-in types, or the introduction of "descriptors", which enable computed properties.
For compatibility reasons, classes are still old-style by default. New-style classes are created by specifying another new-style class (i.e. a type) as a parent class, or the "top-level type" object if no other parent is needed. The behaviour of new-style classes differs from that of old-style classes in a number of important details in addition to what type returns. Some of these changes are fundamental to the new object model, like the way special methods are invoked. Others are "fixes" that could not be implemented before for compatibility concerns, like the method resolution order in case of multiple inheritance.
Python 3 only has new-style classes. No matter if you subclass from object or not, classes are new-style in Python 3. It is however recommended that you still subclass from object.
### Python中,@property和设置-获取哪一个更好
问题[链接](http://stackoverflow.com/questions/6618002/python-property-versus-getters-and-setters)
用属性更好,这也是他们存在的原因。
原因是在Python中,所有属性都是公共的。名字由单下划线或双下划线开始的,只不过是一个警告,表示这个属性的值在只是一个执行细节,在未来的版本中可能不会保持一致。他并没有阻止你去获取或者设置这个属性。因此,标准的属性访问途径便是是公认最好的,Pythonic的。
属性的优点是他们和访问属性的语法上保持一致,所以你可以在不改变客户端的情况下把属性从一个改变成另一个值。你甚至可以有一个不再生产环境版本的类用来保存属性,不用改变代码就可以使用它们(用来debug或者上下文代码)。同时,你不需要为所有东西写获取和设置因为在之后你可能需要更好的控制。
### 在Python中,链式调用父类构造器
问题[链接](http://stackoverflow.com/questions/904036/chain-calling-parent-constructors-in-python)
你正在做的事情,确实是值得推荐的(对于Python 2.x来说)
是否把类明确的传递给`super`是一个风格而不是功能上的问题。把类明确的传递给`super`符合Python哲学的“明了胜于晦涩”。
### Python中,一个对象前面带单下划线和双下划线的含义
问题[链接](http://stackoverflow.com/questions/1301346/the-meaning-of-a-single-and-a-double-underscore-before-an-object-name-in-python)
单下划线
在一个类中,单下划线开头的单纯为了告诉其他程序员,这些属性或者方法意味着私有的。然而,这些属性或者方法本身并没什么特别的。
引述[PEP-8](http://www.python.org/dev/peps/pep-0008/):
_single_leading_underscore: weak "internal use" indicator. E.g. from M import * does not import objects whose name starts with an underscore.
双下划线
来自[Python文档](http://docs.python.org/tutorial/classes.html#private-variables-and-class-local-references):
Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, so it can be used to define class-private instance and class variables, methods, variables stored in globals, and even variables stored in instances. private to this class on instances of other classes.
同一页还有一个警告:
Name mangling is intended to give classes an easy way to define “private” instance variables and methods, without having to worry about instance variables defined by derived classes, or mucking with instance variables by code outside the class. Note that the mangling rules are designed mostly to avoid accidents; it still is possible for a determined soul to access or modify a variable that is considered private.
举例
>>> class MyClass():
... def __init__(self):
... self.__superprivate = "Hello"
... self._semiprivate = ", world!"
...
>>> mc = MyClass()
>>> print mc.__superprivate
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: myClass instance has no attribute '__superprivate'
>>> print mc._semiprivate
, world!
>>> print mc.__dict__
{'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'}
### 在一个已存在的对象里,加一个方法
问题[链接](http://stackoverflow.com/questions/972/adding-a-method-to-an-existing-object)
在Python中,函数和约束方法还是有一些区别。
>> def foo():
... print "foo"
...
>>> class A:
... def bar( self ):
... print "bar"
...
>>> a = A()
>>> foo
<function foo at 0x00A98D70>
>>> a.bar
<bound method A.bar of <__main__.A instance at 0x00A9BC88>>
>>>
约束方法被约束到一个实例上,当方法调用时这个实例会被当做第一个参数传入。
在类(与实例相反)中,那些作为属性的可调用者仍然能是有限制的,尽管,你可以随时修改这个类的定义。
>>> def fooFighters( self ):
... print "fooFighters"
...
>>> A.fooFighters = fooFighters
>>> a2 = A()
>>> a2.fooFighters
<bound method A.fooFighters of <__main__.A instance at 0x00A9BEB8>>
>>> a2.fooFighters()
fooFighters
这样之前定义的实例也回随着更新(只要他们没有重写这个属性):
>>> a.fooFighters()
fooFighters
问题出现在当你想把一个方法固定在某一个实例时:
>>> def barFighters( self ):
... print "barFighters"
...
>>> a.barFighters = barFighters
>>> a.barFighters()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: barFighters() takes exactly 1 argument (0 given)
当你想直接固定到一个实例上时,函数不是自动约束的:
>>> a.barFighters
<function barFighters at 0x00A98EF0>
为了绑定它,我盟可以用[types模块中的方法类函数](http://docs.python.org/library/types.html?highlight=methodtype#module-types):
>>> import types
>>> a.barFighters = types.MethodType( barFighters, a )
>>> a.barFighters
<bound method ?.barFighters of <__main__.A instance at 0x00A9BC88>>
>>> a.barFighters()
barFighters
这时候,类的其他实例不会受到影响:
>>> a2.barFighters()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: A instance has no attribute 'barFighters'
更多的信息,可以在阅读[descriptors](http://users.rcn.com/python/download/Descriptor.htm)和[metaclass](http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html)以及[programming](http://www.gnosis.cx/publish/programming/metaclass_2.html)中发现。
### 在Python中,metaclass是什么
问题[链接](http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python/6581949#6581949)
**类对象**
在理解metaclass之前,你需要掌握Python中的类。而且Python的类的设计,非常的特别,借鉴了Smalltalk语言。
大多数语言中,类只是一段代码用来描述如何生产一个对象。在Python中也有几分这个意思:
>>> class ObjectCreator(object):
... pass
...
>>> my_object = ObjectCreator()
>>> print(my_object)
<__main__.ObjectCreator object at 0x8974f2c>
但是Python中的类不仅仅如此。类,也是对象。
对,对象。
当你使用`class`这个关键字时,Python执行它并创造一个对象,示例:
>>> class ObjectCreator(object):
... pass
...
在内存中创建了一个对象名字是"ObjectCreator"。
这个对象(类)有能力创造对象(实例),这也是为什么它是类。
但它仍然是一个类,因此:
- 你可以把它当做一个变量
- 你可以复制它
- 你可以给它添加属性
- 你可以把它当成一个函数的参数
举例:
>>> print(ObjectCreator) # you can print a class because it's an object
<class '__main__.ObjectCreator'>
>>> def echo(o):
... print(o)
...
>>> echo(ObjectCreator) # you can pass a class as a parameter
<class '__main__.ObjectCreator'>
>>> print(hasattr(ObjectCreator, 'new_attribute'))
False
>>> ObjectCreator.new_attribute = 'foo' # you can add attributes to a class
>>> print(hasattr(ObjectCreator, 'new_attribute'))
True
>>> print(ObjectCreator.new_attribute)
foo
>>> ObjectCreatorMirror = ObjectCreator # you can assign a class to a variable
>>> print(ObjectCreatorMirror.new_attribute)
foo
>>> print(ObjectCreatorMirror())
<__main__.ObjectCreator object at 0x8997b4c>
动态创建类
类就是对象,你可以快速创建它,像任何其他对象一样。
首先,你可以在一个函数里创建一个类,用`class`:
>>> def choose_class(name):
... if name == 'foo':
... class Foo(object):
... pass
... return Foo # return the class, not an instance
... else:
... class Bar(object):
... pass
... return Bar
...
>>> MyClass = choose_class('foo')
>>> print(MyClass) # the function returns a class, not an instance
<class '__main__.Foo'>
>>> print(MyClass()) # you can create an object from this class
<__main__.Foo object at 0x89c6d4c>
但是它不是很动态,你仍然需要手写你的类。
既然类是对象,他们一定可以被什么东西生成。
当你使用`class`关键字时,Python自动创建了这个对象,但是像Python中的其他东西一样,它给你了一个方法手动实现。
还记得`type`函数吗。一个让你知道对象类型的古老的函数:
>>> print(type(1))
<type 'int'>
>>> print(type("1"))
<type 'str'>
>>> print(type(ObjectCreator))
<type 'type'>
>>> print(type(ObjectCreator()))
<class '__main__.ObjectCreator'>
哦,`type`有另外一种完全不同的功能,它也可以迅速创建类。`type`可以把类的描述作为参数,并返回一个类。
(我知道同一个函数根据你传入的值有两种不同的用法是很蠢的,但是它是Python中的一种向后兼容的问题)
`type`这样工作:
type(name of the class,
tuple of the parent class (for inheritance, can be empty),
dictionary containing attributes names and values)
举个例子
>>> class MyShinyClass(object):
... pass
可以通过这种方法手动生成:
>>> MyShinyClass = type('MyShinyClass', (), {}) # returns a class object
>>> print(MyShinyClass)
<class '__main__.MyShinyClass'>
>>> print(MyShinyClass()) # create an instance with the class
<__main__.MyShinyClass object at 0x8997cec>
你可能会注意到我们使用"MyShinyClass"做为类的名字并且作为变量并且作为类的参考。他们可以不同,但是没有必要把事情搞复杂。
`type`接受一个字典,定义一个类的参数,所以:
>>> class Foo(object):
... bar = True
可以理解成:
>>> Foo = type('Foo', (), {'bar':True})
并且可以当成一个普通类来使用:
>>> print(Foo)
<class '__main__.Foo'>
>>> print(Foo.bar)
True
>>> f = Foo()
>>> print(f)
<__main__.Foo object at 0x8a9b84c>
>>> print(f.bar)
True
当然,你可以继承它,所以:
>>> class FooChild(Foo):
... pass
可以是:
>>> FooChild = type('FooChild', (Foo,), {})
>>> print(FooChild)
<class '__main__.FooChild'>
>>> print(FooChild.bar) # bar is inherited from Foo
True
最后你可能想要在你的类里添加方法。只要适当的定义一个函数,然后把它标记为属性。
>>> def echo_bar(self):
... print(self.bar)
...
>>> FooChild = type('FooChild', (Foo,), {'echo_bar': echo_bar})
>>> hasattr(Foo, 'echo_bar')
False
>>> hasattr(FooChild, 'echo_bar')
True
>>> my_foo = FooChild()
>>> my_foo.echo_bar()
True
可以回顾一下:在Python中,类就是对象,你可以动态的创造一个类。
这就是当你使用`class`关键字时Python做的事情,使用metaclass时,也是一样的。
**什么是metaclass(最终版本)**
Metaclass是创建类的原料。
你定义类就是为了创建对象,对不对?
但是我们知道Python类本身就是对象。
所以,这些对象就是metaclass创建的。他们是类的类,你可以这样表述:
MyClass = MetaClass()
MyObject = MyClass()
刚才你看到了`type`允许你做类似这样的事情:
MyClass = type('MyClass', (), {})
这是因为`type`这个函数实际上是一个metaclass。`type`就是metaclass -- Python用来在后台创造一切类。
现在你知道为什么这个东西他喵的写成小写的,而不是`Type`了吧。
嗯,我想同样的问题可能发生在用来创造字符串对象的`str`这个类上,`int`是创造整数对象的类,`type`是用来创造类对象的类。
通过查看`__class__`参数验证。
所有的东西,我是说所有,在Python中都是对象。包括整数,字符串,函数,类。他们全是对象。他们全都由一个类创造而来:
>>> age = 35
>>> age.__class__
<type 'int'>
>>> name = 'bob'
>>> name.__class__
<type 'str'>
>>> def foo(): pass
>>> foo.__class__
<type 'function'>
>>> class Bar(object): pass
>>> b = Bar()
>>> b.__class__
<class '__main__.Bar'>
现在,看看所有的`__class__`的`__class__`是什么?
>>> age.__class__.__class__
<type 'type'>
>>> name.__class__.__class__
<type 'type'>
>>> foo.__class__.__class__
<type 'type'>
>>> b.__class__.__class__
<type 'type'>
所以,metaclass就是用来创造类对象的原料。
如果你想,你可以把他叫做类工厂。
`type`是Python使用的内建的metaclass,当然,你可以创造你自己的metaclass。
**`__metaclass__`属性**
你可以给你写的类添加一个`__metaclass__`属性:
class Foo(object):
__metaclass__ = something...
[...]
如果你这样做,Python会使用metaclass创建`Foo`这个类。
小心点,这很复杂。
你先写了`class Foo(object)`,但是现在在内存中,还没有创建这个类对象`Foo`。
Python会在类的定义时,检查`__metaclass__`。如果找到了,Python就用它创造一个类对象`Foo`。如果没有,就用`type`创造类。
多读几次。
当你这样:
class Foo(Bar):
pass
Python会做下面这些事情:
`Foo`里面有`__metaclass__`这个属性吗?
如果有,在内存中创建一个类对象(我是说一个类对象,与我同在)通过使用`__metaclass__`创建一个同样的名字`Foo`。
如果Python找不到`__metaclass__`,它会在模块层找这个`__metaclass__`,试图通过同样的方式。(但是仅对于那些没有继承任何东西的类,基本上都是旧式类)
之后,如果哪都找不到`__metaclass__`,就使用`Bar`(第一层父类)自带的metaclass(有可能就是缺省的`type`)来创建类对象。
注意,这里的`__metaclass__`不会被继承,父类的会被继承(`Bar.__class__`)。如果`Bar`使用一个用`type`(而不是`type.__new__()`)创建`Bar`本身的`__metaclass__`属性,那么子类不会继承这个行为。
现在一个大问题出现了,你可以在`__metaclass__`里面放什么呢?
答案是:一些可以创建类的东西。
然而什么可以创建类的呢?`type`或者是它的任何子类,或者使用它的东西。
**惯用的metaclass **
一个metaclass的主要目的就是当一个类创建的时候,自动的改变它。
你通常对接口做这些事情,比如你想要创建一个符合当前上下文的类。
试想一个愚蠢的例子,你决定让你的模块里的所有类的所有属性都用大写。有几种方法可以实现,其中一种是在模块层使用`__metaclass__`。
通过这种方法,该模块的所有类在创建时都会使用这个metaclass,而我们只需要告诉metaclass把所有属性都变成大写。
幸运的是,`__metaclass__`可以通过任何方式调用,不需要一个正规的类(我知道,有些名字里带着class的东西不一定是类,想想看吧,它很有用)。
所以我们通过一个函数,从简单的例子开始:
# the metaclass will automatically get passed the same argument
# that you usually pass to `type`
def upper_attr(future_class_name, future_class_parents, future_class_attr):
"""
Return a class object, with the list of its attribute turned
into uppercase.
"""
# pick up any attribute that doesn't start with '__' and uppercase it
uppercase_attr = {}
for name, val in future_class_attr.items():
if not name.startswith('__'):
uppercase_attr[name.upper()] = val
else:
uppercase_attr[name] = val
# let `type` do the class creation
return type(future_class_name, future_class_parents, uppercase_attr)
__metaclass__ = upper_attr # this will affect all classes in the module
class Foo(): # global __metaclass__ won't work with "object" though
# but we can define __metaclass__ here instead to affect only this class
# and this will work with "object" children
bar = 'bip'
print(hasattr(Foo, 'bar'))
# Out: False
print(hasattr(Foo, 'BAR'))
# Out: True
f = Foo()
print(f.BAR)
# Out: 'bip'
现在,我们做同样的事情,但是对metaclass使用真正的类:
# remember that `type` is actually a class like `str` and `int`
# so you can inherit from it
class UpperAttrMetaclass(type):
# __new__ is the method called before __init__
# it's the method that creates the object and returns it
# while __init__ just initializes the object passed as parameter
# you rarely use __new__, except when you want to control how the object
# is created.
# here the created object is the class, and we want to customize it
# so we override __new__
# you can do some stuff in __init__ too if you wish
# some advanced use involves overriding __call__ as well, but we won't
# see this
def __new__(upperattr_metaclass, future_class_name,
future_class_parents, future_class_attr):
uppercase_attr = {}
for name, val in future_class_attr.items():
if not name.startswith('__'):
uppercase_attr[name.upper()] = val
else:
uppercase_attr[name] = val
return type(future_class_name, future_class_parents, uppercase_attr)
但是这并不符合面向对象的思想。我们直接调用`type`,不重写或者调用父类的`__new__`方法。试一下:
class UpperAttrMetaclass(type):
def __new__(upperattr_metaclass, future_class_name,
future_class_parents, future_class_attr):
uppercase_attr = {}
for name, val in future_class_attr.items():
if not name.startswith('__'):
uppercase_attr[name.upper()] = val
else:
uppercase_attr[name] = val
# reuse the type.__new__ method
# this is basic OOP, nothing magic in there
return type.__new__(upperattr_metaclass, future_class_name,
future_class_parents, uppercase_attr)
你可能会主要到多余的参数`upperattr_metaclass`。它没什么特殊的:一个方法总是接受当前的实例作为第一个参数。就像你在普通的方法中使用`self`。
当然,我这里使用这么长的名字是为了更清楚,但是像`self`一样,所有参数有惯用的名字。所以一个真正的生产环境的metaclass看起来可能是这样:
class UpperAttrMetaclass(type):
def __new__(cls, clsname, bases, dct):
uppercase_attr = {}
for name, val in dct.items():
if not name.startswith('__'):
uppercase_attr[name.upper()] = val
else:
uppercase_attr[name] = val
return type.__new__(cls, clsname, bases, uppercase_attr)
我们可以通过使用`super`简化继承,让它更清晰。(因此,你可以拥有metaclasses,继承metaclass,继承type)
class UpperAttrMetaclass(type):
def __new__(cls, clsname, bases, dct):
uppercase_attr = {}
for name, val in dct.items():
if not name.startswith('__'):
uppercase_attr[name.upper()] = val
else:
uppercase_attr[name] = val
return super(UpperAttrMetaclass, cls).__new__(cls, clsname, bases, uppercase_attr)
差不多就这样,metaclass真没什么更多的内容了。
使用metaclass的代码非常复杂的背后原因不是metaclass本身,而是你把metaclass用在了那些自我实现,多重继承的东西上,比如`__dict__`等等。
总之,metaclass有特殊的技巧实现黑魔法,当然包括复杂的东西。但是对他们自己来说,他们很简单:
- 拦截一个类的创建
- 装饰一个类
- 返回装饰过的类
**为什么使用metaclass替代函数**
既然`__metaclass__`可以接受任何调用,为什么你还要使用明显更复杂的类呢?
有几个原因:
- 目的更明确。当你看到`UpperAttrMetaclass(type)`的时候就,你知道接下去会发生什么
- 你可以使用面向对象,metaclass可以继承metaclass,重写父类的方法,Metaclass也可以使用metaclass。
- 你可以更好的组织你的代码结构。不要像上面的例子哪样琐碎的使用metaclass。对某些东西来说它通常是复杂的。创造几个方法并把它们整合到一个类里是很有用的,可以让代码更易读。
- 关联使用`__new__`,`__init__`,和`__call__`。它们允许你做不同的东西,尽管你可以把它们都做在`__new__`里面,有些人用`__init__`更舒服。
- 这些都叫metaclass,靠,它们肯定很有意义。
**你他喵为什么会使用metaclass**
现在有一个大问题,为什么使用这种倾向于引起不清晰的错误的特性?
通常你不会这样:
Metaclass的99%的使用者都不必担心它的深度魔法。如果你不知道你是否需要它们,就别用(那些需要它们的人知道为何用它们,而且不需要解释)
*Python Guru Tim Peters*
metaclass的主要作用就是创造一个接口。典型的用法就是Django ORM。
它允许你这样定义这些东西:
class Person(models.Model):
name = models.CharField(max_length=30)
age = models.IntegerField()
但是你这样用:
guy = Person(name='bob', age='35')
print(guy.age)
它不会返回一个`IntegerField`对象。它会返回一个`int`,甚至能直接从数据库里拿。
这可能是由于`models.Model`为它定义了`__metaclass__`,使用一些魔法方法,让你可以定义一些可以做复杂的事情的简单声明关联数据库。
Django让一些复杂的事情看起来很简单,通过暴露一个简单的接口,使用metaclass,重构了接口的代码让真正的行为在幕后执行。
**结语**
首先你知道类是对象而且可以创建实例。
实际上,类本身也是实例,是metaclass的实例。
>>> class Foo(object): pass
>>> id(Foo)
142630324
所有的东西都是对象,在Python中,它们不是一个类的实例,就是metaclass的实例。
除了`type`。
`type`是它自己的metaclass。这些东西在纯净的Python环境下是看不到的,他们在执行层做了一些交互来实现。
第二,metaclass是复杂的。你不需要在每一个简单的类里使用它。你可以用两种不同的方法来改变一个类:
- [monkey patching](http://en.wikipedia.org/wiki/Monkey_patch)
- 类的装饰器
99%的当你需要改变一个类的时刻,你需要用这些东西。
但是99%的时间里,你不根本不需要改变一个类。
### Python的"最小惊奇":多重默认参数
问题[链接](http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument)
实际上,这不是一个设计瑕疵,而且不它不是因为内部或者表现问题。
它单纯是来自Python中,函数是第一梯队的对象的事实,而且不仅仅是一段代码。
从这个角度,你会发现它很明智:一个函数是一个对象取决于它的定义;默认参数是一种类似丛书数据,而且它们的状态可能从一次到另一次的调用过程中发生改变-和在其他对象中一样。
不管怎样,Effbot在[Default Parameter Values in Python](http://effbot.org/zone/default-values.htm)中对这种表现有一个很好的解释。
我发现它很干净,我强烈推荐阅读以下,并且对函数对象是如何工作的掌握更多知识。
================================================
FILE: contents/qa-others.md
================================================
### 应该在学习Python3之前学习Python2,还是直接学习Python3
问题 [链接](http://stackoverflow.com/questions/170921/should-i-learn-python-2-before-3-or-start-directly-from-python-3)
你可以从python2开始,2和3主要的语法格式和风格相同
3要替代2不是短时间内能完成的,将会是一个很长的过程,所以学习Python2并没有什么坏处
我建议你关注下2和3的不同之处 [This slides gives you a quick introduction of the changes in Python 2 and 3](http://stackoverflow.com/questions/170921/should-i-learn-python-2-before-3-or-start-directly-from-python-3)
### 在virtualenv中如何使用不同的python版本
问题 [链接](http://stackoverflow.com/questions/1534210/use-different-python-version-with-virtualenv)
在创建virtualenv实例时,使用-p选项
virtualenv -p /usr/bin/python2.6 <path/to/new/virtualenv/>
### 如何离开virtualenv
问题 [链接](http://stackoverflow.com/questions/990754/how-to-leave-a-python-virtualenv)
使用virtualenv时
me@mymachine:~$ workon env1
(env1)me@mymachine:~$ workon env2
(env2)me@mymachine:~$ workon env1
(env1)me@mymachine:~$
如何退出某个环境
$ deactivate
### Python中什么项目结构更好
问题 [链接](http://stackoverflow.com/questions/193161/what-is-the-best-project-structure-for-a-python-application)
假设你要开发一个较大的客户端程序(非web端),如何组织项目目录和递归?
不要太在意这个.按你高兴的方式组织就行.Python项目很简单,所以没有那么多愚蠢的规则
/scripts or /bin 命令行脚本
/tests 测试
/lib C-语言包
/doc 文档
/apidoc api文档
并且顶层目录包含README和Config
难以抉择的是,是否使用/src树. /src,/lib,/bin在Python中没有明显的区别,和Java/c不同
因为顶层/src文件夹显得没有什么实际意义,你的顶层目录可以是程序顶层架构的目录
/foo
/bar
/baz
我建议将这些文件放入到"模块名"的目录中,这样,如果你在写一个应用叫做quux, /quux目录将包含所有这些东西
你可以在PYTHONPATH中加入 /path/to/quux/foo,这样你可以QUUX.foo中重用模块
另一个回答
Project/
|-- bin/
| |-- project
|
|-- project/
| |-- test/
| | |-- __init__.py
| | |-- test_main.py
| |
| |-- __init__.py
| |-- main.py
|
|-- setup.py
|-- README
### 在Python中使用Counter错误
问题 [链接](http://stackoverflow.com/questions/13311094/counter-in-collections-module-python)
当使用Counter时,出现异常
AttributeError: 'module' object has no attribute 'Counter'
from collections import Counter
ImportError: cannot import name Counter
原因:
版本问题,Counter在 python2.7中才被加入到这个模块,你可能使用了Python2.6或更老的版本
可以看下 [文档](http://docs.python.org/2/library/collections.html#collections.Counter)
如果要在 Python2.6或2.5版本使用,可以看 [这里](http://code.activestate.com/recipes/576611-counter-class/)
### 在Python中如何连接mysql数据库
问题 [链接](http://stackoverflow.com/questions/372885/how-do-i-connect-to-a-mysql-database-in-python)
首先,安装mysqldb
然后
#!/usr/bin/python
import MySQLdb
db = MySQLdb.connect(host="localhost", # your host, usually localhost
user="john", # your username
passwd="megajonhy", # your password
db="jonhydb") # name of the data base
# you must create a Cursor object. It will let
# you execute all the queries you need
cur = db.cursor()
# Use all the SQL you like
cur.execute("SELECT * FROM YOUR_TABLE_NAME")
# print all the first cell of all the rows
for row in cur.fetchall() :
print row[0]
### Python框架flask和bottle有什么区别
问题 [链接](http://stackoverflow.com/questions/4941145/python-flask-vs-bottle)
区别:flask基于其他现有的存在很长一段时间的技术像Werkzeug和Jinja2,它没有尝试去重复发明轮子
另外一方面,Bottle,试图用一个文件解决一切.
我想去合并他们,但是Bottle的开发者貌似对偏离“一个文件”的处理方式不是很感兴趣
关于可扩展性: 可以使用其他模板引擎,例如Flask-Genshi使用了mako模板
Flask, Werkzeug and Jinja2 的开发者亲自回答的...碉堡了,翻译不是很准确
### 如何测试一个python脚本的性能
问题 [链接](http://stackoverflow.com/questions/582336/how-can-you-profile-a-python-script)
引入
import cProfile
cProfile.run('foo()')
执行脚本
python -m cProfile myscript.py
结果
1007 function calls in 0.061 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.061 0.061 <string>:1(<module>)
1000 0.051 0.000 0.051 0.000 euler048.py:2(<lambda>)
1 0.005 0.005 0.061 0.061 euler048.py:2(<module>)
1 0.000 0.000 0.061 0.061 {execfile}
1 0.002 0.002 0.053 0.053 {map}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler objects}
1 0.000 0.000 0.000 0.000 {range}
1 0.003 0.003 0.003 0.003 {sum}
一个PyCon演讲 [入口](http://blip.tv/pycon-us-videos-2009-2010-2011/introduction-to-python-profiling-1966784)
### 如何获取5分钟之后的unix时间戳
问题 [链接](http://stackoverflow.com/questions/2775864/python-create-unix-timestamp-five-minutes-in-the-future)
使用 [calendar.timegm](http://docs.python.org/3.3/library/calendar.html#calendar.timegm)
future = datetime.datetime.now() + datetime.timedelta(minutes = 5)
return calendar.timegm(future.utctimetuple())
strftime的%s在windows中无法使用
### 在python中如何调用外部命令?
问题 [链接](http://stackoverflow.com/questions/89228/calling-an-external-command-in-python)
Look at the subprocess module in the stdlib:
可以看下标准库中的 [subprocess](http://docs.python.org/library/subprocess.html)
from subprocess import call
call(["ls", "-l"])
subprocess相对于system的好处是, 更灵活
但是 quick/dirty/one time scripts, os.system is enough
### 用Python在终端打印出有颜色的文字?
问题[链接](http://stackoverflow.com/questions/287871/print-in-terminal-with-colors-using-python)
某种程度上这取决于你使用的平台。通常的方法是用ANSI转义序列。举个简单的例子,这有一些来自[blender build scripts](https://svn.blender.org/svnroot/bf-blender/trunk/blender/build_files/scons/tools/bcolors.py)的代码:
class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
为了使用上面那种代码,你应该这样做:
print bcolors.WARNING + "Warning: No active frommets remain. Continue?"
+ bcolors.ENDC
这在unixes包括OS X,linux和windows(为你提供[enable ansi.sys](http://support.microsoft.com/kb/101875))上会生效。有ansi代码来设置颜色,移动光标,做更多事情。
如果你想了解更为复杂的内容(这听上去好像你正在写一款游戏),你应该深入“cursor”这个没款,它会为你处理很多复杂的部分。[Python Curses HowTO](https://docs.python.org/2/howto/curses.html)是一篇很好的介绍。
如果你是用的不是ASCII(或者说你没有用PC),你面对诸如ascii字符低于127,’#’,‘@’可能是你得到空格的最好的赌注。如果你确定你的终端使用IBM [extended ascii character set](http://telecom.tbi.net/asc-ibm.html),你将会有更多的选择,字符176,字符177,字符178,和字符219代表”空格字符”。
一些流行的基于文本的程序,比如”Dwarf Fortress”,仿照文本的模式做成了图形模式,使用传统PC的字体图片。你可以在[Dwarf Frotress Wiki](http://dwarffortresswiki.org/DF2014:Tilesets)找一些这种点阵图看看([user-made tilesets](http://dwarffortresswiki.org/Tileset_repository))。
[Text Mode Demo Contest](http://en.wikipedia.org/wiki/TMDC)有更多把图片处理成文本的源码。
嗯...我想这个问题被我扯远了。尽管我现在纠结着去做一款基于文本的史诗冒险游戏。在有颜色的文本这方面,祝你好运。
### 我该如何保护我的Python代码
Python作为字节码编译的解释型语言,是很难封闭的。几遍你使用一种exe包比如[py2exe](http://py2exe.org/),可执行文件的结构依然是清晰可见的,而且Python的字节编码是非常易懂的。
通常是这样,你必须要想出一个折衷的办法。保护代码究竟重不重要。里面是不是有很私密的东西(比如银行的对称加密秘钥),或者你是一个偏执狂。选择一门可以让你更快速开发优秀产品的语言,对于你的奇特想法从现实主义考虑一下它的价值。
如果你确定使用要强制授权保证安全,可以写一个小的C拓展,那么这个授权检验就会变得很难逆转(但不是完全不可能)。然后把你的大批代码放进Python。
### 首选的Python单元测试框架
问题[链接](http://stackoverflow.com/questions/191673/preferred-python-unit-testing-framework)
`nose`实际上不是一个单元测试的框架。它是一个测试的执行器,并且是最好的一款。它可以运行通过`pyUnit`,`py.test`和`doctest`创建的测试。
我首选的单元测试框架是pyUnit。它和其他xUnit框架一样,而且可以让没有Python基础的人很好上手。而且它对Eclipse/PyDev提供非常好的支持。
在`py.test`中,我发现了很多层级的安装/卸载混淆在一起。我还发现它生成了很多非常无组织和难阅读的单元测试。
`doctest`对于简单的东西来说还好,但是它很有限,不能真正的用来测试复杂和交互的代码。
### Python的单元测试放在哪?
问题[链接](http://stackoverflow.com/questions/61151/where-do-the-python-unit-tests-go)
对于一个文件`module.py`来说,单元测试通常叫做`test_module.py`,遵循Python的命名规则。
在以下几种地方放置`test_module.py`都是可以接受的:
1. 和`module.py`放在同一个文件夹。
2. 在`../tests/test_module.py`(与代码文件夹的同级)
3. 在`tests/test_module.py` (在代码文件夹下的同层)
我倾向第一种方法,它可以更直观的被找到并且引入。不管你在使用什么样的开发系统,你都可以轻松的配置并找到以`test_`开头的文件。实际上,方便查找的缺省的单元测试模型是`test*.py`。
### distribute, distutils, setuptools和distutils2的区别
问题[链接](http://stackoverflow.com/questions/6344076/differences-between-distribute-distutils-setuptools-and-distutils2)
到2014年9月,所有其他回答的时间都超过一年了。当你寻求Python打包的建议时,记得看一下发布的日期,而且不要相信过时的信息。
这篇搭建在Readthedocs的文章[Python Packaging User Guide](http://stackoverflow.com/questions/6344076/differences-between-distribute-distutils-setuptools-and-distutils2)值得一读。每一页都有一个最近时间展示,所以你可以检查最新的手册,而且它相当的全面。Python 3.4的官方文档已经从信任的角度把这个链接加进来了。
工具的总结:
这里有一个2014年9月份的Python打包总结:
* **Distutils** is still the standard tool for packaging in Python. It is included in the standard library (Python 2 and Python 3.0 to 3.4). It is useful for simple Python distributions, but lacks features. It introduces the distutils Python package that can be imported in your setup.py script.
* **Setuptools** was developed to overcome Distutils' limitations, and is not included in the standard library. It introduced a command-line utility called easy_install. It also introduced the setuptools Python package that can be imported in your setup.py script, and the pkg_resources Python package that can be imported in your code to locate data files installed with a distribution. One of its gotchas is that it monkey-patches the distutils Python package. It should work well with pip. The latest version was released in August 2014.
* **Distribute** was a fork of Setuptools. It shared the same namespace, so if you had Distribute installed, import setuptools would actually import the package distributed with Distribute. Distribute was merged back into Setuptools 0.7, so you don't need to use Distribute any more. In fact, the version on Pypi is just a compatibility layer that installs Setuptools.
* **Distutils2** was an attempt to take the best of Distutils, Setuptools and Distribute and become the standard tool included in Python's standard library. The idea was that Distutils2 would be distributed for old Python versions, and that Distutils2 would be renamed to packaging for Python 3.3, which would include it in its standard library. These plans did not go as intended, however, and currently, Distutils2 is an abandoned project. The latest release was in March 2012, and its Pypi home page has finally been updated to reflect its death.
* **Distlib** is a tool that aims to implement a subset of the previous tools' functionality, but only functionality that is very well-defined in accepted PEPs. It should hopefully be included eventually in the Python standard library. It is still being developed and is not recommended for end-users yet.
* **Bento** is a packaging solution designed to replace Distutils, Setuptools, Distribute and Distutils2, written from the ground up. Its primary developer is also a core developer of numpy/scipy, so he's familiar with non-simple use-cases for packaging systems. Its first commit was in October 2009, and the latest commit as of writing was in August 2014, although the authors are not updating its Pypi page correspondingly. It's in active development but it is not mature yet, and it is not as widely known as Setuptools yet.
推荐:
所以综上所述,排除所有这些选项,我回推荐 **Setuptools**,除非你的需求非常基础,那么你可能只需要 Distutils。Setuptools在Virtualenv和Pip上的表现非常好,我强烈推荐。
作为一个边注,我建议使用Virtualenv1.10或者更高的版本,因为对Python2或3来说,它是第一个识别Setuptools/Distribute并合并的版本。
================================================
FILE: contents/qa-pip-easy_install.md
================================================
### 如何使用 pip 更新所有包
问题 [链接](http://stackoverflow.com/questions/2720014/upgrading-all-packages-with-pip)
如何使用pip更新python的所有包
没有内置的标志可以实现
但是你可以这么做
pip freeze --local | grep -v '^\-e' | cut -d = -f 1 | xargs pip install -U
### 如何删除Python easy_install安装的包
问题 [链接](http://stackoverflow.com/questions/1231688/how-do-i-remove-packages-installed-with-pythons-easy-install)
[pip](https://pypi.python.org/pypi/pip/), setuptools/easy_install的另一种选择,提供uninstall命令
首先,移除依赖
$ easy_install -m [PACKAGE]
然后,手动删除egg文件
$ rm -rf .../python2.X/site-packages/[PACKAGE].egg
### 如何获取Python的site-packages目录位置
问题 [链接](http://stackoverflow.com/questions/122327/how-do-i-find-the-location-of-my-python-site-packages-directory)
参考 [How to Install Django" documentation](http://docs.djangoproject.com/en/dev/topics/install/#remove-any-old-versions-of-django)
可以在shell中执行
python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"
更好的可读性
from distutils.sysconfig import get_python_lib
print(get_python_lib())
### setup.py安装后如何卸载
问题 [链接](http://stackoverflow.com/questions/1550226/python-setup-py-uninstall)
使用下面命令安装的包如何卸载
python setup.py install
手工删除的话
python setup.py install --record files.txt
cat files.txt | xargs rm -rf
### 如何获取安装的python模块列表
问题 [链接](http://stackoverflow.com/questions/739993/get-a-list-of-installed-python-modules)
>>> help('modules')
### 为什么要使用pip而不是easy_install
问题 [链接](http://stackoverflow.com/questions/3220404/why-use-pip-over-easy-install)
有一条推文
Don't use easy_install, unless you like stabbing yourself in the face. Use pip.
Pip简介
All packages are downloaded before installation. Partially-completed installation doesn’t occur as a result.
Care is taken to present useful output on the console.
The reasons for actions are kept track of. For instance, if a package is being installed, pip keeps track of why that package was required.
Error messages should be useful.
The code is relatively concise and cohesive, making it easier to use programmatically.
Packages don’t have to be installed as egg archives, they can be installed flat (while keeping the egg metadata).
Native support for other version control systems (Git, Mercurial and Bazaar)
Uninstallation of packages.
Simple to define fixed sets of requirements and reliably reproduce a set of packages.
其他原因:
Another—as of yet unmentioned—reason for favoring pip is because it is the new hotness and will continue to be used in the future.
pip提供unstall命令
如果中途安装失败,pip will leave you in a clean state.
### 如何在正确使用pip,virtualenv,distribute构建Python环境
问题[链接](http://stackoverflow.com/questions/4324558/whats-the-proper-way-to-install-pip-virtualenv-and-distribute-for-python)
你可以不向Python本身添加任何东西。
你不需要sudo或者任何权限。
你不需要编辑任何文件。
在自引导的虚拟环境里安装virtualenv。通过这个虚拟环境,它可以创建更多。自从virtualenv搭载了pip和distribute,你就可以从其中一个获得所有东西。
1. 下载virtualenv:
http://pypi.python.org/pypi/virtualenv
https://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.9.tar.gz(实际上最好下载最新的版本!)
2. 解压源码
3. 用解压好的源文件创建一个干净的虚拟环境。选择正确的命令,虚拟环境会自带pip和distribute。
4. 在virtualenv中安装virtualenv
5. 使用第一个自建的环境去创建更多!
有一个bash的简单例子:
# Select current version of virtualenv:
VERSION=1.6.4
# Name your first "bootstrap" environment:
INITIAL_ENV=py-env0
# Options for your first environment:
ENV_OPTS='--no-site-packages --distribute'
# Set to whatever python interpreter you want for your first environment:
PYTHON=$(which python)
URL_BASE=http://pypi.python.org/packages/source/v/virtualenv
# --- Real work starts here ---
curl -O $URL_BASE/virtualenv-$VERSION.tar.gz
tar xzf virtualenv-$VERSION.tar.gz
# Create the first "bootstrap" environment.
$PYTHON virtualenv-$VERSION/virtualenv.py $ENV_OPTS $INITIAL_ENV
# Don't need this anymore.
rm -rf virtualenv-$VERSION
# Install virtualenv into the environment.
$INITIAL_ENV/bin/pip install virtualenv-$VERSION.tar.gz
现在你可以用你的自引导环境去创建更多:
# Create a second environment from the first:
$INITIAL_ENV/bin/virtualenv --no-site-packages --distribute py-env1
# Create more:
$INITIAL_ENV/bin/virtualenv py-env2
疯狂吧!
更新
`—no-site-packages` and`—distribute`现在是默认的了(运行`virtualenv -h`)所以你可以通过`python virtualenv.py bootstrap`或者`python3 virtualenv.py bootstrap`安装你的引导。
================================================
FILE: contents/qa-std-modules.md
================================================
### json和simplejson的区别
问题 [链接](http://stackoverflow.com/questions/712791/json-and-simplejson-module-differences-in-python)
json就是simple,加入到标准库. json在2.6加入,simplejson在2.4+,2.6+,更有优势
另外,simplejson更新频率更高,如果你想使用最新版本,建议用simplejson
好的做法是
try: import simplejson as json
except ImportError: import json
另外,可以关注二者性能上的比较
### 如何用http下载一个文件
问题 [链接](http://stackoverflow.com/questions/22676/how-do-i-download-a-file-over-http-using-python)
直接使用urllib
import urllib
urllib.urlretrieve ("http://www.example.com/songs/mp3.mp3", "mp3.mp3")
使用urllib2,并提供一个进度条
import urllib2
url = "http://download.thinkbroadband.com/10MB.zip"
file_name = url.split('/')[-1]
u = urllib2.urlopen(url)
f = open(file_name, 'wb')
meta = u.info()
file_size = int(meta.getheaders("Content-Length")[0])
print "Downloading: %s Bytes: %s" % (file_name, file_size)
file_size_dl = 0
block_sz = 8192
while True:
buffer = u.read(block_sz)
if not buffer:
break
file_size_dl += len(buffer)
f.write(buffer)
status = r"%10d [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
status = status + chr(8)*(len(status)+1)
print status,
f.close()
使用第三方[requests](http://docs.python-requests.org/en/latest/index.html)包
>>> import requests
>>>
>>> url = "http://download.thinkbroadband.com/10MB.zip"
>>> r = requests.get(url)
>>> print len(r.content)
10485760
### argparse可选位置参数
问题 [链接](http://stackoverflow.com/questions/4480075/argparse-optional-positional-arguments)
脚本运行 usage: installer.py dir [-h] [-v]
dir是一个位置参数,定义如下
parser.add_argument('dir', default=os.getcwd())
我想让dir变为可选,如果未设置,使用os.getcwd()
不幸的是,当我不指定dir时,得到错误 "Error: Too few arguments"
尝试使用 nargs='?'
parser.add_argument('dir', nargs='?', default=os.getcwd())
例子
>>> import os, argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('-v', action='store_true')
_StoreTrueAction(option_strings=['-v'], dest='v', nargs=0, const=True, default=False, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('dir', nargs='?', default=os.getcwd())
_StoreAction(option_strings=[], dest='dir', nargs='?', const=None, default='/home/vinay', type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args('somedir -v'.split())
Namespace(dir='somedir', v=True)
>>> parser.parse_args('-v'.split())
Namespace(dir='/home/vinay', v=True)
>>> parser.parse_args(''.split())
Namespace(dir='/home/vinay', v=False)
>>> parser.parse_args(['somedir'])
Namespace(dir='somedir', v=False)
>>> parser.parse_args('somedir -h -v'.split())
usage: [-h] [-v] [dir]
positional arguments:
dir
optional arguments:
-h, --help show this help message and exit
-v
### 有什么方法可以获取系统当前用户名么?
问题 [链接](http://stackoverflow.com/questions/842059/is-there-a-portable-way-to-get-the-current-username-in-python)
至少在Linux和Windows下都可用.就像 os.getuid
>>> os.getuid()
42
>>> os.getusername()
'slartibartfast'
可以看看 [getpass](http://docs.python.org/2/library/getpass.html) 模块
>>> import getpass
>>> getpass.getuser()
'kostya'
可用: Unix, Windows
### 在Python中如何解析xml
问题 [链接](http://stackoverflow.com/questions/1912434/how-do-i-parse-xml-in-python)
<foo>
<bar>
<type foobar="1"/>
<type foobar="2"/>
</bar>
</foo>
如何解析获取xml文件中内容
我建议使用 [ElementTree](http://docs.python.org/2/library/xml.etree.elementtree.html) (有其他可用的实现,例如 [lxml](http://lxml.de/),他们只是更快, ElementTree提供更简单的编程api)
在使用XML建立Element实例之后,例如使用 [XML](http://docs.python.org/2/library/xml.etree.elementtree.html#xml.etree.ElementTree.XML) 函数
for atype in e.findall('type')
print(atype.get('foobar'))
### 如何使用Python创建一个GUID
问题 [链接](http://stackoverflow.com/questions/534839/how-to-create-a-guid-in-python)
如何使用原生的python创建一个GUID?
Python2.5及以上版本,使用[uuid](http://docs.python.org/2/library/uuid.html)模块
>>> import uuid
>>> uuid.uuid1()
UUID('5a35a426-f7ce-11dd-abd2-0017f227cfc7')
### 我该使用urllib/urllib2还是requests库
问题 [链接](http://stackoverflow.com/questions/2018026/should-i-use-urllib-or-urllib2-or-requests)
[requests](http://docs.python-requests.org/en/latest/index.html)
推荐使用requests库
1. 支持restful API
import requests
...
resp = requests.get('http://www.mywebsite.com/user')
resp = requests.post('http://www.mywebsite.com/user')
resp = requests.put('http://www.mywebsite.com/user/put')
resp = requests.delete('http://www.mywebsite.com/user/delete')
2. 无论GET/POST,你不需要关注编码
userdata = {"firstname": "John", "lastname": "Doe", "password": "jdoe123"}
resp = requests.post('http://www.mywebsite.com/user', params=userdata)
3. 内建json decoder
resp.json()
resp.text #纯文本
4. 其他 建官方文档
urllib2,提供了一些额外的函数,让你可以自定义request headers
r = Request(url='http://www.mysite.com')
r.add_header('User-Agent', 'awesome fetcher')
r.add_data(urllib.urlencode({'foo': 'bar'})
response = urlopen(r)
注意:urlencode只有urllib中有
### Python中是否存在方法可以打印对象的所有属性和方法
问题 [链接](http://stackoverflow.com/questions/192109/is-there-a-function-in-python-to-print-all-the-current-properties-and-values-of)
使用pprint
from pprint import pprint
pprint (vars(your_object))
### 如何展示一个正在运行的Python应用的堆栈踪迹
问题[链接](http://stackoverflow.com/questions/132058/showing-the-stack-trace-from-a-running-python-application)
我一般在这种情况下用这个模块-当一个进程会跑很长时间,但是有时被莫名其妙而且不重复出现的原因卡住。看上去有点黑客的感觉,并且只在unix上生效(依赖信号):
import code, traceback, signal
def debug(sig, frame):
"""Interrupt running process, and provide a python prompt for
interactive debugging."""
d={'_frame':frame} # Allow access to frame object.
d.update(frame.f_globals) # Unless shadowed by global
d.update(frame.f_locals)
i = code.InteractiveConsole(d)
message = "Signal received : entering python shell.\nTraceback:\n"
message += ''.join(traceback.format_stack(frame))
i.interact(message)
def listen():
signal.signal(signal.SIGUSR1, debug) # Register handler
使用时,当你启动程序时,只需要调用listen()这个函数(你甚至可以放到site.py里,对所有Python程序都起效),让它运行起来。任何时候,都可以对进程发出一个SIGUSR1的信号,使用kill或者在Python中:
os.kill(pid, signal.SIGUSR1)
这会使Python控制台程序在当时停止,并给你展示堆栈的踪迹,允许你操作所有的变量。使用control-d(EOF)继续运行(在发出信号的一刻,通过注释你可以打断任何I/O等等,所以它不是完全无害的)。
我还有一个可以做同样事情的脚本,唯一不同的是它可以和正在运行的进程通过pip互通(允许在后台进行程序排错等等)。粘贴到这可能太长了,我已经把它加进了[python cookbook recipe](http://code.activestate.com/recipes/576515/)。
### 在Python中,有什么办法杀死一个线程
问题[链接](http://stackoverflow.com/questions/323972/is-there-any-way-to-kill-a-thread-in-python)
不论是在Python中还是其他语言,突然停止一个线程通常来讲是一个很不好的习惯。考虑下面的情况:
- 线程携带了非常重要的数据必须要正确的关闭
- 线程创建了其余的进程,杀死这一个,其余的也要被杀掉
如果你承担得起(比如你再操纵自己的线程),那么比较好的做法是创建一个exit_request标记,每一个线程都会定时的检查是不是轮到它退出了。
举个例子:
import threading
class StoppableThread(threading.Thread):
"""Thread class with a stop() method. The thread itself has to check
regularly for the stopped() condition."""
def __init__(self):
super(StoppableThread, self).__init__()
self._stop = threading.Event()
def stop(self):
self._stop.set()
def stopped(self):
return self._stop.isSet()
上述代码,当你想要停止这个线程时,你可以调用stop()方法,然后等待线程退出,最好用join()。线程应该定时的检查stop这个标记。
当然,某些情况下,你有足够的理由必须杀死一个线程。比如你正在封装一个外部的库,而且它已经持续很长时间了,你需要打断它。
下面的代码允许(可能有些限制)在Python中触发一个异常。
def _async_raise(tid, exctype):
'''Raises an exception in the threads with id tid'''
if not inspect.isclass(exctype):
raise TypeError("Only types can be raised (not instances)")
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,
ctypes.py_object(exctype))
if res == 0:
raise ValueError("invalid thread id")
elif res != 1:
# "if it returns a number greater than one, you're in trouble,
# and you should call it again with exc=NULL to revert the effect"
ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
raise SystemError("PyThreadState_SetAsyncExc failed")
class ThreadWithExc(threading.Thread):
'''A thread class that supports raising exception in the thread from
another thread.
'''
def _get_my_tid(self):
"""determines this (self's) thread id
CAREFUL : this function is executed in the context of the caller
thread, to get the identity of the thread represented by this
instance.
"""
if not self.isAlive():
raise threading.ThreadError("the thread is not active")
# do we have it cached?
if hasattr(self, "_thread_id"):
return self._thread_id
# no, look for it in the _active dict
for tid, tobj in threading._active.items():
if tobj is self:
self._thread_id = tid
return tid
# TODO: in python 2.6, there's a simpler way to do : self.ident
raise AssertionError("could not determine the thread's id")
def raiseExc(self, exctype):
"""Raises the given exception type in the context of this thread.
If the thread is busy in a system call (time.sleep(),
socket.accept(), ...), the exception is simply ignored.
If you are sure that your exception should terminate the thread,
one way to ensure that it works is:
t = ThreadWithExc( ... )
...
t.raiseExc( SomeException )
while t.isAlive():
time.sleep( 0.1 )
t.raiseExc( SomeException )
If the exception is to be caught by the thread, you need a way to
check that your thread has caught it.
CAREFUL : this function is executed in the context of the
caller thread, to raise an excpetion in the context of the
thread represented by this instance.
"""
_async_raise( self._get_my_tid(), exctype )
正如注释中所写,这并不是一个万能钥匙,如果一个线程在Python解释器之外跑着,那么它不会被抓住并打断。
上面这段代码的一个好用法,就是让线程捕获一个特殊的异常并且表现的很干净。这样才能如你所愿的利落的中断一个任务。
### Python中isinstance()和type()的区别
总结一下其他人的答案(已OK的)作为内容。`isinstance`为继承者们服务(某个父类的实例也是基类的一个实例),而只检查是否相等的`type`则不是这样(他要求某个类型的id,拒绝子类型的实例,也可以叫做子类)
在Python中,通常你希望你的代码支持继承,当然(自从继承变得很容易之后,通过使用你自己的而不是使用它本身来停止某些代码是很不好的),所以`isinstance`看上去比检查id的`type`s要好一些,因为它无缝支持继承。
这不是说`isinstance`就绝对好,提醒一下,只是比对比类型是否相等好一点。通常从Pythonic的角度出发,最好的解决办法是永远的鸭子类型:试着像用一个渴望得到的类型去使用某个参数,用`try/except`声明捕获所有该参数不属于我们的渴望的类型而引起的异常(或者任何类鸭子类型;-),然后在`except`从句中,试着做一些其他的事情(假设这个参数“可能是”某些类型)
`basestring`时一个奇葩,这是一个存在的意义仅仅是为了让你使用`isinstance`的内建类型(同理他们的子类`str`和`Unicode`)。字符串是有序的(你可以循环,排序,切片...),但是通常你对待它们就像标准类型--由于某些原因它不太好用(但是我们相当频繁的使用他们),原因是我们对于所有的字符串(或者其他标准类型,比如一个不能回环的东西)都用同一种方法,所有的容器(列表,集合,字典...),另一方面`basestring`加上`isinstance`可以帮你做这种事情--这个习惯用法的全部结构看起来像这样:
if isinstance(x, basestring)
return treatasscalar(x)
try:
return treatasiter(iter(x))
except TypeError:
return treatasscalar(x)
你可能会说`basestring`是一个抽象类--在子类中没有提供具体的功能,更多的时候充当一个标记,为了让我们使用`isinstance`。从[PEP 3119](http://www.python.org/dev/peps/pep-3119/)开始,这种观念越来越明显,介绍了它的泛型,在Python2.6和3.0中被采用并实现。
PEP明确了抽象基类可以代替鸭子类型,而且实现起来没什么压力(看[这里](https://www.python.org/dev/peps/pep-3119/#abcs-vs-duck-typing))。最新版本的Python中实现的抽象基类提供了额外的更吸引人的东西:`isinstance`(和`issubclass`)现在不仅仅是一个子类的实例(特别是所有的类都可以注册成为抽象基类并展示为某个子类,它可以实例化抽象基类的实例),抽象基类还为具体的子类提供了更多的便利-自然的通过模板方法来设计模仿应用。(看[这里](http://en.wikipedia.org/wiki/Template_method_pattern)和[这里](http://www.catonmat.net/blog/learning-python-design-patterns-through-video-lectures/)(第三部分)了解Python中特殊不特殊的更多TM DP,以及抽象基类的支持)。
对于那些Python 2.6中潜在的关于抽象基类的技巧,看[这里](https://docs.python.org/2/library/abc.html),对于3.1版本,同样,看[这里](https://docs.python.org/3.1/library/abc.html)。两种版本的基本库模块[collections](https://docs.python.org/3.1/library/collections.html#module-collections)(这是3.1版本,几乎一样的2.6版本,看[这里](https://docs.python.org/2/library/collections.html#module-collections))都提供了多种有用的抽象基类。
这个答案的目的是,抽象基类保留的那些关键东西(我们可以超过论证横向比较TM DP的功能性,和Python传统的mixin类,比如[UserDict.DictMixin](https://docs.python.org/2/library/userdict.html#UserDict.DictMixin))是他们让`isinstance`(和`issubclass`)比之前(Python2.5及之前)更有魅力且无处不在(在Python2.6以及更新的版本中)。因此,相比之下,在Python中检查类型相等更恶心了,比之前的版本还糟糕。
================================================
FILE: contents/qa-string.md
================================================
### 为什么是string.join(list)而不是list.join(string)
问题 [链接](http://stackoverflow.com/questions/493819/python-join-why-is-it-string-joinlist-instead-of-list-joinstring)
my_list = ["Hello", "world"]
print "-".join(my_list)
#为什么不是 my_list.join("-") 。。。。这个....
答案:
因为所有可迭代对象都可以被连接,而不只是列表,但是连接者总是字符串
### 字符如何转为小写
问题 [链接](http://stackoverflow.com/questions/6797984/how-to-convert-string-to-lowercase-in-python)
s = "Kilometer"
print(s.lower())
### 字符串转为float/int
>>> a = "545.2222"
>>> float(a)
545.2222
>>> int(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '545.2222'
>>> int(float(a))
545
>>> int('544')
544
另一种,用 [ast](http://docs.python.org/2/library/ast.html#ast.literal_eval)模块
>>> import ast
>>> ast.literal_eval("545.2222")
545.2222
>>> ast.literal_eval("31")
31
### 如何反向输出一个字符串
问题 [链接](http://stackoverflow.com/questions/931092/reverse-a-string-in-python)
做法
>>> 'hello world'[::-1]
'dlrow olleh'
### 如何随机生成大写字母和数字组成的字符串
6U1S75
4Z4UKK
U911K4
解决
import string, random
''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(N))
### python中字符串的contains
问题 [链接](http://stackoverflow.com/questions/3437059/does-python-have-a-string-contains-method)
python中字符串判断contains
使用in关键字
if not "blah" in somestring: continue
if "blah" not in somestring: continue
使用字符串的find/index (注意index查找失败抛异常)
s = "This be a string"
if s.find("is") == -1:
print "No 'is' here!"
else:
print "Found 'is' in the string."
### 如何判断一个字符串是数字
问题 [链接](http://stackoverflow.com/questions/354038/how-do-i-check-if-a-string-is-a-number-in-python)
使用这种方法会不会十分丑陋和低效
def is_number(s):
try:
float(s)
return True
except ValueError:
return False
使用这种方法并不丑陋和低效
使用isdigit(缺点,对非整数无能为力)
a = "03523"
a.isdigit()
### 字符串格式化 % vs format
问题 [链接](http://stackoverflow.com/questions/5082452/python-string-formatting-vs-format)
Python2.6中引入string.format()方法,语法和原先%操作符的字符串格式化差异较大
在什么情况下使用哪种更好?
以下的输出是一致的,有什么区别
#!/usr/bin/python
sub1 = "python string!"
sub2 = "an arg"
a = "i am a %s"%sub1
b = "i am a {0}".format(sub1)
c = "with %(kwarg)s!"%{'kwarg':sub2}
d = "with {kwarg}!".format(kwarg=sub2)
print a
print b
print c
print d
.format 看起来更加强大,可以用在很多情况.
例如你可以在格式化时重用传入的参数,而你用%时无法做到这点
另一个比较讨厌的是,%只处理 一个变量或一个元组, 你或许会认为下面的语法是正确的
"hi there %s" % name
但当name恰好是(1,2,3)时,会抛出TypeError异常.为了保证总是正确的,你必须这么写
"hi there %s" % (name,) # supply the single argument as a single-item tuple
这么写很丑陋, .format没有这些问题
什么时候不考虑使用.format
你对.format知之甚少
使用Python2.5
### 将一个字符串转为一个字典
问题 [链接](http://stackoverflow.com/questions/988228/converting-a-string-to-dictionary)
如何将字符串转成字典,不适用eval
s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"
从python2.6开始,你可以使用内建模块 ast.literal_eval
>>> import ast
>>> ast.literal_eval("{'muffin' : 'lolz', 'foo' : 'kitty'}")
{'muffin': 'lolz', 'foo': 'kitty'}
这个做法比直接eval更安全
帮助文档
>>> help(ast.literal_eval)
Help on function literal_eval in module ast:
literal_eval(node_or_string)
Safely evaluate an expression node or a string containing a Python
expression. The string or node provided may only consist of the following
Python literal structures: strings, numbers, tuples, lists, dicts, booleans,
and None.
举例
>>> eval("shutil.rmtree('mongo')")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
File "/opt/Python-2.6.1/lib/python2.6/shutil.py", line 208, in rmtree
onerror(os.listdir, path, sys.exc_info())
File "/opt/Python-2.6.1/lib/python2.6/shutil.py", line 206, in rmtree
names = os.listdir(path)
OSError: [Errno 2] No such file or directory: 'mongo'
>>> ast.literal_eval("shutil.rmtree('mongo')")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/Python-2.6.1/lib/python2.6/ast.py", line 68, in literal_eval
return _convert(node_or_string)
File "/opt/Python-2.6.1/lib/python2.6/ast.py", line 67, in _convert
raise ValueError('malformed string')
ValueError: malformed string
### 如何获取一个字符的ASCII码
问题 [链接](http://stackoverflow.com/questions/227459/ascii-value-of-a-character-in-python)
>>> ord('a')
97
>>> chr(97)
'a'
>>> chr(ord('a') + 3)
'd'
>>>
另外对于unicode
>>> unichr(97)
u'a'
>>> unichr(1234)
u'\u04d2'
### 如何使用不同分隔符切分字符串
问题 [链接](http://stackoverflow.com/questions/1059559/python-strings-split-with-multiple-separators)
使用re.split [文档](http://docs.python.org/2/library/re.html#re.split)
>>> re.split('\W+', 'Words, words, words.')
['Words', 'words', 'words', '']
>>> re.split('(\W+)', 'Words, words, words.')
['Words', ', ', 'words', ', ', 'words', '.', '']
>>> re.split('\W+', 'Words, words, words.', 1)
['Words', 'words, words.'])
或者匹配获取正确的 re.findall
import re
DATA = "Hey, you - what are you doing here!?"
print re.findall(r"[\w']+", DATA)
# Prints ['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']
### 如何截掉空格(包括tab)
问题 [链接](http://stackoverflow.com/questions/1185524/how-to-trim-whitespace-including-tabs)
空白在字符串左右两边
s = " \t a string example\t "
s = s.strip()
空白在字符串右边
s = s.rstrip()
左边
s = s.lstrip()
另外你可以指定要截掉的字符作为参数
s = s.strip(' \t\n\r')
### 如何截取一个字符串获得子串
问题 [链接](http://stackoverflow.com/questions/663171/is-there-a-way-to-substring-a-string-in-python)
>>> x = "Hello World!"
>>> x[2:]
'llo World!'
>>> x[:2]
'He'
>>> x[:-2]
'Hello Worl'
>>> x[-2:]
'd!'
>>> x[2:-2]
'llo Worl'
python将这类操作称为切片,可以作用于序列类型,不仅仅是字符串
### python中用==比较字符串,is有时候会返回错误判断
问题 [链接](http://stackoverflow.com/questions/1504717/python-vs-is-comparing-strings-is-fails-sometimes-why)
is是身份测试,==是相等测试
>>> a = 'pub'
>>> b = ''.join(['p', 'u', 'b'])
>>> a == b
True
>>> a is b
False'
is 等价于 id(a) == id(b)
### 如何填充0到数字字符串中保证统一长度
问题 [链接](http://stackoverflow.com/questions/339007/python-nicest-way-to-pad-zeroes-to-string)
对于字符串
>>> n = '4'
>>> print n.zfill(3)
>>> '004'
对于数字,[相关文档](http://docs.python.org/2/library/string.html#formatexamples)
>>> n = 4
>>> print '%03d' % n
>>> 004
>>> print "{0:03d}".format(4) # python >= 2.6
>>> 004
>>> print("{0:03d}".format(4)) # python 3
>>> 004
### 如何将字符串转换为datetime
字符串 -> time [strptime](https://docs.python.org/2/library/time.html#time.strptime)
>>> import time
>>> time.strptime("30 Nov 00", "%d %b %y")
time.struct_time(tm_year=2000, tm_mon=11, tm_mday=30, tm_hour=0, tm_min=0,
tm_sec=0, tm_wday=3, tm_yday=335, tm_isdst=-1)
time -> 字符串 [strftime](https://docs.python.org/2/library/time.html#time.strftime)
>>> from time import gmtime, strftime
>>> strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())
'Thu, 28 Jun 2001 14:17:15 +0000'
### 如何将byte array转为string
问题 [链接](http://stackoverflow.com/questions/606191/convert-byte-array-to-python-string)
>>> b"abcde"
b'abcde'
>>> b"abcde".decode("utf-8")
'abcde'
================================================
FILE: contents/qa-tuple.md
================================================
### Python中的命名元组是什么?
问题[链接](http://stackoverflow.com/questions/2970608/what-are-named-tuples-in-python)
命名元组基本上是一种易创建,轻量的对象类型。命名元组实例像值引用一样被对象引用或者使用基础的元组语法。他们可以像`struct`或者其他常用的记录类型一样被使用,除了他们是不可变的。他们在Python 2.6和Python 3.0中被加入。尽管有一个[在Python2.4中实现的秘诀](http://code.activestate.com/recipes/500261/)
举个例子,通常我们要顶一个点,用元组表示`(x, y)`。用代码写出来像下面这样:
pt1 = (1.0, 5.0)
pt2 = (2.5, 1.5)
from math import sqrt
line_length = sqrt((pt1[0]-pt2[0])**2 + (pt1[1]-pt2[1])**2)
使用命名元组可以更可读:
from collections import namedtuple
Point = namedtuple('Point', 'x y')
pt1 = Point(1.0, 5.0)
pt2 = Point(2.5, 1.5)
from math import sqrt
line_length = sqrt((pt1.x-pt2.x)**2 + (pt1.y-pt2.y)**2)
然而,命名元组仍然向下兼容普通的元组,所以下面的代码仍然有效:
Point = namedtuple('Point', 'x y')
pt1 = Point(1.0, 5.0)
pt2 = Point(2.5, 1.5)
from math import sqrt
# use index referencing
line_length = sqrt((pt1[0]-pt2[0])**2 + (pt1[1]-pt2[1])**2)
# use tuple unpacking
x1, y1 = pt1
因此,如果你认为对象标记可以让你的代码更Pythonic、更可读,那么请将所有的元组替换为命名元组。我个人已经开始使用命名元组去替代非常简单的值类型,尤其是那些要作为参数传入函数的东西。它让函数不用知道元组的包装内容,更加具有可读性。
长远点说,你还可以用命名元组替代不含方法的普通不可变类。你还可以把你的命名元组类型作为基类:
class Point(namedtuple('Point', 'x y')):
[...]
当然,作为元组,命名元组中的属性仍然是不可变的:
>>> Point = namedtuple('Point', 'x y')
>>> pt1 = Point(1.0, 5.0)
>>> pt1.x = 2.0
AttributeError: can't set attribute
如果你想改变这些值,你需要另一个类型。有一个方便的方法[mutable recordtypes](http://code.activestate.com/recipes/576555/),它允许你把修改属性为新的值。
>>> from rcdtype import *
>>> Point = recordtype('Point', 'x y')
>>> pt1 = Point(1.0, 5.0)
>>> pt1 = Point(1.0, 5.0)
>>> pt1.x = 2.0
>>> print(pt1[0])
2.0
我仍然不知道有任何”命名列表“的结构,可以让你添加新的区块。这种情况下你可能只是需要用一个字典。命名元组可以转化成字典,用`pt1._asdict()`可以返回`{'x': 1.0, 'y': 5.0}`而且升级为可以使用所有字典常用的函数。
已经标记过的,你应该[查看文档](https://docs.python.org/3/library/collections.html#collections.namedtuple)来获取更多搭建这些例子的信息。
gitextract_lw7pi0h1/
├── README.md
└── contents/
├── qa-built-in.md
├── qa-control-flow.md
├── qa-datetime.md
├── qa-dict.md
├── qa-exception.md
├── qa-file.md
├── qa-func.md
├── qa-list.md
├── qa-math.md
├── qa-modules.md
├── qa-oop.md
├── qa-others.md
├── qa-pip-easy_install.md
├── qa-std-modules.md
├── qa-string.md
└── qa-tuple.md
Condensed preview — 17 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (220K chars).
[
{
"path": "README.md",
"chars": 20593,
"preview": "stackoverflow-py-top-qa\n=======================\n\n\nNotice:\n\n 目前进度90%, 剩余40+个问题实在没时间翻了, 有兴趣的同学可以试试, 提pr. or后续我找时间处理完整.\n"
},
{
"path": "contents/qa-built-in.md",
"chars": 7111,
"preview": "\n\n### 如何flush Python的print输出\n\n问题 [链接](http://stackoverflow.com/questions/230751/how-to-flush-output-of-python-print)\n重复问"
},
{
"path": "contents/qa-control-flow.md",
"chars": 7113,
"preview": "### 如何结束退出一个python脚本\n\n问题 [链接](http://stackoverflow.com/questions/73663/terminating-a-python-script)\n\n import sys\n "
},
{
"path": "contents/qa-datetime.md",
"chars": 3256,
"preview": "\n### 如何将一个Python time.struct_time对象转换为一个datetime对象\n\n问题 [链接](http://stackoverflow.com/questions/1697815/how-do-you-conver"
},
{
"path": "contents/qa-dict.md",
"chars": 4581,
"preview": "\n### 使用列表解析创建一个字典\n\n问题 [链接](http://stackoverflow.com/questions/1747817/python-create-a-dictionary-with-list-comprehension"
},
{
"path": "contents/qa-exception.md",
"chars": 3989,
"preview": "\n### Python中声明exception的方法\n\n问题 [链接](http://stackoverflow.com/questions/1319615/proper-way-to-declare-custom-exceptions-i"
},
{
"path": "contents/qa-file.md",
"chars": 7498,
"preview": "\n### 如何判断一个文件是否存在\n\n问题 [链接](http://stackoverflow.com/questions/82831/how-do-i-check-if-a-file-exists-using-python)\n\n如何检查一"
},
{
"path": "contents/qa-func.md",
"chars": 10488,
"preview": "\n### 如何获取一个函数的函数名字符串\n\n问题 [链接](http://stackoverflow.com/questions/251464/how-to-get-the-function-name-as-string-in-python"
},
{
"path": "contents/qa-list.md",
"chars": 9372,
"preview": "### 序列的切片操作\n\n问题 [链接](http://stackoverflow.com/questions/509211/the-python-slice-notation)\n\nIt's pretty simple really:\n很简"
},
{
"path": "contents/qa-math.md",
"chars": 20332,
"preview": "\n### 在Python中如何展示二进制字面值\n\n问题 [链接](http://stackoverflow.com/questions/1476/how-do-you-express-binary-literals-in-python)\n\n"
},
{
"path": "contents/qa-modules.md",
"chars": 5336,
"preview": "\n### \\_\\_init\\_\\_.py是做什么用的\n\n问题 [链接](http://stackoverflow.com/questions/448271/what-is-init-py-for)\n\n\n这是包的一部分,[具体文档](http"
},
{
"path": "contents/qa-oop.md",
"chars": 30211,
"preview": "\n### Python 'self' 解释\n\n问题 [链接](http://stackoverflow.com/questions/2709821/python-self-explained)\n\n\nself关键字的作用是什么?\n我理解他用户"
},
{
"path": "contents/qa-others.md",
"chars": 10886,
"preview": "\n\n### 应该在学习Python3之前学习Python2,还是直接学习Python3\n\n问题 [链接](http://stackoverflow.com/questions/170921/should-i-learn-python-2-b"
},
{
"path": "contents/qa-pip-easy_install.md",
"chars": 4367,
"preview": "\n### 如何使用 pip 更新所有包\n\n问题 [链接](http://stackoverflow.com/questions/2720014/upgrading-all-packages-with-pip)\n\n如何使用pip更新pytho"
},
{
"path": "contents/qa-std-modules.md",
"chars": 12559,
"preview": "\n### json和simplejson的区别\n\n问题 [链接](http://stackoverflow.com/questions/712791/json-and-simplejson-module-differences-in-pyt"
},
{
"path": "contents/qa-string.md",
"chars": 7377,
"preview": "### 为什么是string.join(list)而不是list.join(string)\n\n问题 [链接](http://stackoverflow.com/questions/493819/python-join-why-is-it-s"
},
{
"path": "contents/qa-tuple.md",
"chars": 1907,
"preview": "### Python中的命名元组是什么?\n\n问题[链接](http://stackoverflow.com/questions/2970608/what-are-named-tuples-in-python)\n\n命名元组基本上是一种易创建,"
}
]
About this extraction
This page contains the full source code of the wklken/stackoverflow-py-top-qa GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 17 files (163.1 KB), approximately 56.6k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.