rainit2006 / Python-room

my python room
0 stars 0 forks source link

Basic tutorial #1

Open rainit2006 opened 7 years ago

rainit2006 commented 7 years ago

学習サイト

rainit2006 commented 7 years ago

--

rainit2006 commented 7 years ago

显示python版本号 在Python窗口里:

>>> import sys
>>> sys.version_info

在windows cmd里: python -V (V必须是大写)

Exiting from python Command Line Use exit() or Ctrl-Z plus Return to exit。

print exit 时,会显示出如何exit。比如:exit()

安装某库文件

cd到该库文件的目录下
python setup.py install
rainit2006 commented 7 years ago

ply PLYは、lexとyaccをPythonで実装し直したツールです。 执行easy_install ply报错说找不到合适的distribution。所以从https://pypi.python.org/pypi/ply下载安装包执行“python setup.py install”。

??lex yacc是什么??

Pycharm

Anaconda Anaconda は、Continuum Analytics 社によって提供されている、Python 本体に加え、科学技術、数学、エンジニアリング、データ分析など、よく利用される Python パッケージ(2016 年 2 月時点で 400 以上)を一括でインストール可能にしたパッケージです。面倒なセットアップ作業が効率よく行えるため、Python 開発者の間で広く利用されています。なお、Anaconda は商用目的にも利用可能です。

Spyder Spyder(以前はPydee)はオープンソースでクロスプラットフォームな統合開発環境であり、Pythonで科学用途のプログラミングをすることを意図して作られている。SpyderにはNumPy・SciPy・Matplotlib・IPythonなどが統合されている。

Jupyter Notebook Jupyter Notebook (読み方は「ジュパイター・ノートブック」または「ジュピター・ノートブック」) とは、ノートブックと呼ばれる形式で作成したプログラムを実行し、実行結果を記録しながら、データの分析作業を進めるためのツールです。 プログラムとその実行結果やその際のメモを簡単に作成、確認することができるため、自分自身の過去の作業内容の振り返りや、チームメンバーへ作業結果を共有する際に便利なほか、スクール形式での授業や研修などでの利用にも向いています。

Python でデータサイエンス http://pythondatascience.plavox.info/

rainit2006 commented 6 years ago

■print

print('apple', i, 0.123, sep='\n')

apple

100

0.123


- パーセント%を使うprintf形式
文字列 % 変数
変換指定子は整数が%d 或 %i、浮動小数点が%f、文字列が%s。其他类型参考:
https://docs.python.jp/3/library/stdtypes.html#printf-style-string-formatting

s = 'Alice' i = 25

print('Alice is %d years old' % i)

Alice is 25 years old

print('%s is %d years old' % (s, i))

Alice is 25 years old


文字列メソッドformat()
文字列.format(変数)

print('Alice is {} years old'.format(i))

Alice is 25 years old

print('{} is {} years old'.format(s, i))

Alice is 25 years old

print('{0} is {1} years old / {0}{0}{0}'.format(s, i))

Alice is 25 years old / AliceAliceAlice

print('{name} is {age} years old'.format(name=s, age=i))

Alice is 25 years old

#文字列中の波括弧{, }をそのまま出力したい場合は{{, }}とする。


f文字列(フォーマット文字列)

s = 'Alice' i = 25

print(f'{s} is {i} years old')

Alice is 25 years old


数値をフォーマットして出力(桁数指定など)

number = 0.45 print('{0:.4f} is {0:.2%}'.format(number))

0.4500 is 45.00%

print(f'{number:.4f} is {number:.2%}')

0.4500 is 45.00%


数値を2進数、8進数、16進数表記の文字列に変換
方法1、組み込み関数

bi = 255 bin_str = bin(i) oct_str = oct(i) hex_str = hex(i) print(bin_str) print(oct_str) print(hex_str)

0b11111111

0o377

0xff

in(), oct(), hex()

方法2、組み込み関数format()または文字列メソッドstr.format()
第二引数の書式化指定文字列にb, o, xを指定すること

bin_str = format(i, 'b') oct_str = format(i, 'o') hex_str = format(i, 'x')

print(bin_str) print(oct_str) print(hex_str)

11111111

377

ff

print(type(bin_str)) print(type(oct_str)) print(type(hex_str))

<class 'str'>

<class 'str'>

<class 'str'>


**■Basic syntax**
- One liners

Java: int temp = x; x = y; y = temp;

Python:
x, y = y, x

rainit2006 commented 6 years ago

collectionsモジュール

応用例:単語の数え上げ

from collections import Counter

data = ['aaa', 'bbb', 'ccc', 'aaa', 'ddd']
counter = Counter(data)
for word, cnt in counter.most_common():
    print word, cnt # =>
                    #   aaa 2
                    #   bbb 1
                    #   ccc 1
                    #   ddd 1
rainit2006 commented 6 years ago
rainit2006 commented 6 years ago

PyQt ■ Python初心者が、1日でPyQtを使って数値計算用のGUIアプリを作成する http://hope-is-dream.hatenablog.com/entry/2015/01/24/143402

■ インストール方法 http://qiita.com/Algebra_nobu/items/d49044308397070ca0dd ①Anacondaをインストールします ②インストールしたPythonのIDEのSpyderを起動します。 ③Spyderを開いたら右下のConsoleタブを開きます。右上にあるOptionsボタンを選択して、「Open command prompt」をクリックします。 ③そのコンソール画面で   pip install virtualenv  と入力し、実行します。virtualenvがインストールされます。 ④同じくコンソール画面で   virtualenv pyqt   cd pyqt/Scripts   activate  を実行します。これで仮想環境が作成されました。  そして、PyQt5をインストールします。   pip install pyqt5 ⑤ サンプルコードを実行してみる

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import QApplication, QWidget

if __name__ == '__main__':

    app = QApplication(sys.argv)

    w = QWidget()
    w.resize(250, 150)
    w.move(300, 300)
    w.setWindowTitle('Simple')
    w.show()

    sys.exit(app.exec_())

image

■ Qt算是发明了signal/slot,这个思想也被其他一些框架语言借鉴了。 谈signal/slot之前先来谈谈C++的缺欠,这个问题也被讨论很多了,这里只谈一点,C++的设计目标是面向对象语言,它不仅提供了对象的定义和构建的方式,也定义了对象间的关系,比如 继承 派生 聚合,但是它没有提供对象间通信和共享数据的方式,这个缺点在一般程序的开发上不算个大问题,我们可以自己简单实现,但是对于GUI开发,这个缺点就被放大了很多倍。

说到通信和共享,其实他们是一回事,共享很多时候就是为了通信,而C++里要通信就必然要共享。比如,一个类实例拥有另一个的指针,就可以访问对方的数据,调用对方的方法了,这实际就是共享了一个指针,这个类指针也是另一个对象的this。访问数据和调用方法其实都是通信,把对方的数据拿过来,把自己的数据送过去,交换数据就是通信。 在C++里,由于没有GC,管理大量原生指针是极其危险的,对象的生命周期不可控,野指针的出现概率会很高,大型C++ 的GUI项目参与开发的人数众多,很难保证都不犯错。 那么用观察者模式呢?其实也一样,还是共享了IObserverXXX指针。 那么发消息行不行呢?比如 MFC那样,可以,但是本质上还是共享了窗口句柄,否则消息发给谁呢?而且还带来另外的问题,就是类型安全,消息的参数是无法类型安全的。

Qt作为大型GUI项目的Framework,它必须解决这个问题,否则这个程序是写不大的,写大了就会问题层出不穷。

看看Qt 的解决方案:

Window::Window()
{
    QPushButton *b = new QPushButton(this);
    connect(b, SIGNAL(clicked()), SLOT(on_button_clicked()));
}

Window::on_button_clicked()
{
    QPushButton *b = qobject_cast<QPushButton*>(sender());
    b->setText("clicked!");
}

这段代码,通过Qt的signal slot机制,把QPushButton的点击事件连接到了Window的on_button_clicked响应函数上。Window 和 QPushButton并没有互相保存对方指针,QPushButton的指针b 只是个局部变量,用过之后很快销毁,Window和QPushButton实现了通信,数据共享,事件响应,但是却没有共享指针,而且他们不受对方的生命周期影响,无论谁先销毁,这段代码都不会出错。这种方式还是类型安全的,当signal和slot的类型不匹配的时候 connect是会报错的。

signal/slot为对象间通信提供了非常灵活方便的实现,如果你只关心一个signal那就可以只connect一个,可以多个slot连接同一个signal,也可以一个slot连接到多个signal,Qt会负责管理连接关系和对象生命周期,对象销毁时会自动断开连接。Qt为了实现signal/slot也是付出代价的,在无法改变C++语法的情况下,只能通过moc预编译器来扩展关键字。这大概是独一无二的实现方式了,后来的signal/slot实现要不用C++ template,或者发明种语言直接做到语法里,比如C# delegate。

作者:姚冬 链接:https://www.zhihu.com/question/27040542/answer/35141912

■ C#的delegate机制 : delegate可以粗暴地理解为一个函数的指针。delegate出来的目的是为了实现两个component之间的通信。


     public delegate void SomeMethodPtr();
     static void Main(string[] args)
    {
        SomeMethodPtr obj = new SomeMethodPtr(SomeMethod);
        obj.invoke();
    }

   static void SomeMethod(){....}

delegate就是把函数包装成对象,然后传来传去。应用场景 :callback函数。 为了满足high order function(函数做参数和返回值)的需求,c#就捣鼓出了delegate。 在一些支持函数对象的语言(js,Python)中自然不需要把它包起来。 python版本

def summation(n, term, next): 
    total, k = 0, 1 
    while k <= n: 
        total, k = total + term(k), next(k) 
    return total

对应的C#delegate版本 (Func<>相当于 singlecast delegate)

public double Sumation(int n, Func<int, double> term, Func<int, int> next)
{
    double total = 0;
    int k = 1;
    while (k<=n)
    {
        total += term(k);
        k = next(k);
    }
    return total;
}
rainit2006 commented 6 years ago

環境変数の取得と設定

rainit2006 commented 6 years ago

常用字符处理

def camelcase_to_uppercase(s): rv = [] for c in s: if c in string.asciiuppercase: rv.append("") rv.append(c) return "".join(rv).upper() print(camelcase_to_uppercase(r'HappyDay'))

输出: _HAPPY_DAY



- "0"*8 = "00000000", 即连续8个"0"字符.

- 字符串取前4位 :  Jdate[0:4]
rainit2006 commented 6 years ago

virtualenv pythonにはvirtualenvという仮想環境が簡単に作れるモジュールがある。お試しに何かモジュールをインストールしたい場合、virutalenvで環境を作ってそちらにインストールして試せば、システム環境は無傷で使える。いくつも環境が作れるのでpythonのバージョンで分けたりと色々と便利なのだ。

virtualenvとそれを簡単に管理できるvirtualenvwrapperをセットで導入するのが便利.

仮想環境の作成 仮想環境を作りたいプロジェクトにcdし、以下のようなコマンドを叩くと、仮想環境が作成されます。 仮想環境名は任意の名称で構いません。

#  @特定プロジェクトに、仮想環境myenvを作成する。
$ cd (仮想環境を作りたいプロジェクト)
$ virtualenv myenv

# 仮想環境myenvを有効化する
$ source myenv/bin/activate

# コンソール上に、以下のように表示されれば成功です!
(myenv) $ 

# 作成したばかりの時点では、仮想環境はクリーンな状態です。
# 試しにpip freezeすると、最低限のパッケージしかインストールされていないことがわかります。
(myenv) $ pip freeze
appdirs==1.4.3
packaging==16.8
pyparsing==2.2.0
six==1.10.0

仮想環境の無効化・削除

# 仮想環境の無効化
(myenv) $ deactivate

# 仮想環境の削除
# (プロジェクト直下に生成されたフォルダを、まるごと削除でOKです。)
$ rm -rf myenv/

利用virtualenv做成一个python3的环境: virtualenv -p python3 envname

How Use Virtualenv with Python with Visual Studio Code in Ubuntu Quite Simple with latest VSCode, if you have installed Official Python extension for VSCode. Shift + Command + PType : Python: Select Interpreter Choose your virtual env.

rainit2006 commented 6 years ago

tqdm 進捗を表示する.

for文で何万回というループをまわして処理待ちをする時,今だいたいどこらへんまで進んだのか?というのを確認したくて思わず if i % 1000 == 0: print('now =', i) みたいなコードを書いてしまったりしますが,そのためのライブラリを使うと簡単かつよりリッチな情報を得ることができます.個人的には tqdm というライブラリを使っています.

#!/usr/bin/env python

from tqdm import tqdm
import time

def main():
    for i in tqdm(range(100)):
        time.sleep(0.02)

if __name__ == '__main__': main()

python tqdm tutorial https://www.youtube.com/watch?v=v1P-ZbCEAww

rainit2006 commented 6 years ago

ログを取る関数を用意する 本来は loggingモジュールを使うのが筋かもしれませんが,自分が書くようなスクリプトの場合だと自前で書いてしまった方が速い&小回りが効く場合があるので以下のlog()みたいな関数を用意することが多いです.

<t5.py>

#!/usr/bin/env python
import datetime

def log(*args):
    msg = ' '.join(map(str, [datetime.datetime.now(), '>'] + list(args)))
    print(msg)
    with open('log.txt', 'at') as fd: fd.write(msg + '\n')

def main():
    log('generated', 5, 'items')

if __name__ == '__main__': main()

$ python t5.py 2017-09-04 12:39:38.894456 > generated 5 items $ cat log.txt 2017-09-04 12:39:38.894456 > generated 5 items

Note:数値が入ったリストの文字列変換

>>>list = [0,1,2,3,4,5]
>>>map(str,list)
['0', '1', '2', '3', '4', '5']
rainit2006 commented 6 years ago

argparseでパラメータを管理する https://www.sejuku.net/blog/23647 コマンドライン引数を扱いやすくしてくれるモジュールです。 ヘルプと使用方法のメッセージを作成し、引数の指定に誤りがあった場合にエラーを発生させます。

argparseモジュールのArgumentParserクラスのコンストラクタを使用してパーサーを生成します。 パーサーとは構文解析を行うプログラムや処理のことです。 生成したパーサーからparse_argsメソッドを呼び出し実行すると、引数を解析しヘルプが表示できるようになります。 またArgumentParserクラスのコンストラクタの引数には以下のような設定ができるようになっています。 ・prog プログラム名を入力 ・usage プログラムの利用方法を記述 ・description 引数の説明の前に表示される説明文 ・epilog 引数の説明の後に表示される文字列 ・add_help [-h]/[–help]オプションの追加の有無

引数を追加するためにArgumentParserクラスのadd_argumentメソッドを使用します。 add_argumentメソッドはパーサーを生成した後で、parse_argsメソッドで引数の解析を行う前に指定します。

add_argumentメソッドの引数には下記のような設定ができるようになっています。 ・name or flags 位置引数もしくはオプション引数の指定 ・help 引数の簡単な説明 ・action 引数の取り扱いの指定 ・required 引数の省略可否(オプション引数のみ) ・type 引数が変換される型 ・choises 引数として許される値の指定 ・nargs 引数の数の指定 ・default 引数がなかった場合に生成される値 ・metavar メッセージで表示される引数の名前

choices: 引数には許される値を指定することができ、choicesの項目で指定します。choicesの項目で指定した以外の値を指定すると、エラー「error: argument」が出力表示されます。

nargsについて 引数の数を指定する場合はnargsの項目で指定します。 指定した数以外で指定すると、エラー「error: the following arguments are required」が表示されます。

import argparse

# パーサーを作る
parser = argparse.ArgumentParser(
            prog='argparseTest', # プログラム名
            usage='Demonstration of argparser', # プログラムの利用方法
            description='description', # 引数のヘルプの前に表示
            epilog='end', # 引数のヘルプの後で表示
            add_help=True, # -h/–help オプションの追加
            )

# 引数の追加
parser.add_argument('-v', '--verbose', help='select mode',
                    type=int,
                    choices=[0,1])
parser.add_argument('i', help='integer',
                    type=int)

# 引数を解析する
args = parser.parse_args()

if args.verbose == 0:
    if args.i % 2 == 1:
        print(str(args.i) + ' : Odd')
    else:
        print(str(args.i) + ' : Even')
elif args.verbose == 1:
    if args.i % 2 == 1:
        print(str(args.i) + ' : 奇数')
    else:
        print(str(args.i) + ' : 偶数')

実行結果:

$ python3 argparseTest.py 3 -v 0
3 : Odd
$ python3 argparseTest.py 3 -v 1
3 : 奇数
$ python3 argparseTest.py 3 -v 2
usage: Demonstration of argparser
argparseTest: error: argument -v/--verbose: invalid choice: 2 (choose from 0, 1)
$ python3 argparseTest.py -h
usage: Demonstration of argparser
description

positional arguments:
  i                     integer

optional arguments:
  -h, --help            show this help message and exit
  -v {0,1}, --verbose {0,1}
                        select mode
end

FileTypeについて コマンドの引数として入力するファイルパス名や出力するファイルパス名を指定することもあります。 入力するファイルパス名を指定する場合はargparse.FileType(‘r’)と指定します。 出力するファイルパス名を指定する場合はargparse.FileType(‘w’)と指定します。

import argparse

# パーサーを作る
parser = argparse.ArgumentParser(
            prog='argparseTest', # プログラム名
            usage='Demonstration of argparser', # プログラムの利用方法
            description='description', # 引数のヘルプの前に表示
            epilog='end', # 引数のヘルプの後で表示
            add_help=True, # -h/–help オプションの追加
            )

# 引数の追加
parser.add_argument('infile', help='inputfile',
                    type=argparse.FileType('r'))
parser.add_argument('outfile', help='outputfile',
                    type=argparse.FileType('w'))

# 引数を解析する
args = parser.parse_args()

message = args.infile.read()
args.infile.close();
args.outfile.write(message + '\n' + 'Good bye')
args.outfile.close()

defaultについて オプション引数を指定しない場合にdefaultの項目で指定した値を使用して処理します。

<实用例>

#!/usr/bin/env python

import argparse

def main():
    # パーサの作成
    psr = argparse.ArgumentParser()
    # -w / --word というオプションを追加.デフォルトは 'hello! '
    psr.add_argument('-w', '--word', default='hello! ')
    # -s / --size というオプションを追加,デフォルトは5で型はint
    psr.add_argument('-s', '--size', default=5, type=int)
    # コマンドラインの引数をパースしてargsに入れる.エラーがあったらexitする
    args = psr.parse_args()
    print(args.word * args.size) //重复输出字符串多次(次数为args.size)

if __name__ == '__main__': main()

python t3.py -s 6 hello! hello! hello! hello! hello! hello! python t3.py -s 2 hello! hello! python t3.py -w 'hoge ' hoge hoge hoge hoge hoge

rainit2006 commented 6 years ago

列表处理 更新列表: append方法

list = []          ## 空列表
list.append('Google')   ## 使用 append() 添加元素
list.append('Runoob')
print list

删除列表元素: del方法

list1 = ['physics', 'chemistry', 1997, 2000]

print list1
del list1[2]
print "After deleting value at index 2 : "
print list1

Python列表脚本操作符

Python 表达式 | 结果 | 描述 len([1, 2, 3]) | 3 | 长度 [1, 2, 3] + [4, 5, 6] | [1, 2, 3, 4, 5, 6] | 组合 ['Hi!'] * 4 | ['Hi!', 'Hi!', 'Hi!', 'Hi!'] | 重复 3 in [1, 2, 3] | True | 元素是否存在于列表中 for x in [1, 2, 3]: print x, | 1 2 3 | 迭代

rainit2006 commented 6 years ago

基本数据类型 list, tuple, dic, set https://blog.csdn.net/u014745194/article/details/70147193

my_list = ['python', 'js', 'SQL'] my_tuple = (['python', 'js', 'SQL']) my_set = {'python', 'js', 'SQL'}

在 Python 中,我們使用 list 串列和 tuple 元組來儲存序列式資料。兩者最大的不同在於 tuple 是不可以改變的。

应用场景: list, 简单的数据集合,可以使用索引; tuple, 把一些数据当做一个整体去使用,不能修改; dict,使用键值和值进行关联的数据; set,数据只出现一次,只关心数据是否出现, 不关心其位置;

■list 1,list是列表的意思。 2,底层是链表。列表是序列对象,使用一对方括号[ ]。可包含任意的Python数据信息,如字符串、数字、列表、元组等。列表的数据是可变的,我们可通过对象方法对列表中的数据进行增加、修改、删除等操作。 3,可以通过list(seq)函数把一个序列类型转换成一个列表。 常用方法:

1,append(y) 在列表尾部追加单个对象y。使用多个参数会引起异常。
2,count(y) 返回对象y在列表中出现的次数。
3,extend(L) 将列表L中的表项添加到列表中。返回None。
4,index(y) 返回列表中匹配对象y的第一个列表项的索引。无匹配元素时产生异常。
5,insert(i,y) 在索引为i的元素前插入对象y。如list.insert(0,y)在第一项前插入对象。返回None。
6,pop(y) 删除列表中索引为y的表项,并返回该表项的值。若未指定索引,pop返回列表最后一项。
7,remove(y) 删除列表中匹配对象y的第一个元素。无匹配元素时产生异常,返回None。
8,reverse() 颠倒列表元素的顺序。 默认值为False,要想颠倒列表元素顺序,则设为True
9,sort() 对列表排序,返回none。bisect模块可用于排序列表项的添加和删除。

■tuple 1,tuple是元组的意思. 2,元组将”多样的对象”集合到一起,不能修改,通过索引可以进行查找, 使用括号一对圆括号()。 3,因为tuple不可变,所以代码更安全。如果可能,能用tuple代替list就尽量用tuple。

一些注意事项: 1,tuple=(1,),只有1个元素的tuple定义时必须加一个逗号,来消除歧义。 因为()不仅用来表示tuple数据结构,还可以用来数学中的公式。这就产生了歧义,因此,Python规定,在t(1)这种情况下,按小括号进行计算,计算结果自然是1。 2,tuple=1,2,3,4,这也可以是一个元组,在不使用圆括号而不会导致混淆时,Python允 许不使用圆括号的元组。建议少这样写。 3,和列表一样,可对元组进行索引、分片、连接和重复。也可用len()求元组长度。 4,元组的索引用tuple[y]的形式,而不是tuple(y)。切记切记。 5,和列表类似,使用tuple(arg)可把其它序列类型转换成元组。 6, 看一个例子:

m = (‘aa’, ‘bb’, [‘AA’, ‘BB’])
m[2][0] = ‘XX’
m[2][1] = ‘YY’
print(m)
(‘aa’, ‘bb’, [‘XX’, ‘YY’])
表面上看,tuple的元素确实变了,但其实变的不是tuple的元素,而是list的元素。tuple一开始指向的list并没有改成别的list,所以,tuple所谓的“不变”是说,tuple的每个元素,指向永远不变。

■字典 http://www.runoob.com/python/python-dictionary.html

dict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'};

dict['Age'] = 8; # update existing entry
dict['School'] = "DPS School"; # Add new entry

print "dict['Age']: ", dict['Age'];
print "dict['School']: ", dict['School'];

利用zip函数

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

if __name__ == '__main__':
    keys = ['cat', 'dog', 'mouse']
    values = ['nya-nya-', 'wanwan', 'chu-chu-']
    print(dict(zip(keys, values)))

判断元素是否在dict里 ①キー in 辞書オブジェクト ②辞書オブジェクト.has_key(キー)

如何追加新元素:

方法1, default_data['item3'] = 3
方法2,default_data.update({'item3': 3}) # update方法可以更新或追加新元素
 you can use update to add more than one item.
default_data.update({'item4': 4, 'item5': 5})

https://www.pythonweb.jp/tutorial/dictionary/index5.html

■ set 定义: 1,set是集合的意思。 2,无序,元素只出现一次, 自动去重,使用”set([ ])”。在创建set的时候,需要提供一个list作为输入。 3,因此set中的元素和dict中的key一样,只能是string,number和tuple等不可变的元素,而不能是list。

一些注意事项: 1,set和list可以自由转换,在删除list中多个/海量重复元素时,可以先转换成set,然后再转回list并排序(set没有排序)。此种方法不仅方便且效率较高. 2,set.add(),set.update.set.remove,添加更新删除,-= 可以做set减法 3,set.discard 和 set.remove不同在于如果删除的元素不在集合内,discard不报错,remove 报错

< <= 表示 子集,> >=表示超集 | 表示联合, & 表示交集 ,- 表示差集, ^ 差分集

リスト型との決定的な違いは ・重複した要素がない ・要素に順番がない

myset1 = set([1,2,3])
myset2 = set([1,2,3,3,2,1])
print(myset1)
print(myset2)
結果:
{1, 2, 3}
{1, 2, 3}

■What is the difference between list and tuples? image

rainit2006 commented 5 years ago

■ What is the difference between deep and shallow copy? Ans: Shallow copy is used when a new instance type gets created and it keeps the values that are copied in the new instance. Shallow copy is used to copy the reference pointers just like it copies the values. These references point to the original objects and the changes made in any member of the class will also affect the original copy of it. Shallow copy allows faster execution of the program and it depends on the size of the data that is used.

Deep copy is used to store the values that are already copied. Deep copy doesn’t copy the reference pointers to the objects. It makes the reference to an object and the new object that is pointed by some other object gets stored. The changes made in the original copy won’t affect any other copy that uses the object. Deep copy makes execution of the program slower due to making certain copies for each object that is been called.

# コード
a = "abc"
b = a

print ("id(a) = %s" % id(a))
print ("id(b) = %s" % id(b))

# 実行結果
id(a) = 4339645944
id(b) = 4339645944

このように、二つの変数が、同じオブジェクトを指していることがわかります。

copy模块有copy.copy和copy.deepcopy两种方法。 对于对象(比如二次元数组)来说,copy.copy是浅拷贝,copy.deepcopy是深拷贝。

代码参考: https://github.com/rainit2006/Python-room/blob/master/Python-Project/Sample/Basic/copy_test.py

rainit2006 commented 5 years ago

if name == 'main': って何? 「if name == 'main':」の意味は、「直接実行された場合のみ実行し、それ以外の場合(例、importされた場合)は実行しない」

nameはPythonプリンタでPythonスクリプトを読み込むと自動的に作成される。 Pythonスクリプトを直接実行した時には、そのスクリプトファイルは「main」という名前のモジュールとして認識される。

rainit2006 commented 5 years ago

Loop処理

-2次配列のloop

ex, test_data is a {2:[], 4:[]} array.

for group in test_set:    ##group are 2, 4
    for data in test_set[group]:  
             do something.

ex2,

dataset = {'k':[[1,2],[2,3],[3,1]], 'r':[[6,5],[7,7],[8,6]]}
new_features = [5,7]
[[plt.scatter(ii[0],ii[1],s=100,color=i) for ii in dataset[i]] for i in dataset]
# same as:
##for i in dataset:
##    for ii in dataset[i]:
##        plt.scatter(ii[0],ii[1],s=100,color=i)

Yield: ジェネレータ, generator yeild は •関数の処理を 一旦停止 し •値を返す

メリット:メモリの効率化が上げられます。yieldのほうが効率が良い場合があるんです。 単純な例ですが、たとえば 1GB の巨大なテキストファイルがあるとします。そして、この巨大なファイルを読み込み、データを渡してくれる関数を作るとします。 これを普通にやろうとすると、受け渡し用のメモリが 1GB という巨大なサイズになってしまいます。 ところが yield を使えば、少量、たとえば 1 行づつデータを読み込み、その都度 yield すればいいので、メモリの使用量はほんの僅かで済んでしまいます http://ailaby.com/yield/

image

例子:斐波那契数列

def fab(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a+b
        n = n + 1

for i in fab(10):
    print(i)
rainit2006 commented 5 years ago

可変長引数(args, kwargs) args: 複数の引数をタプルとして受け取る kwargs: 複数のキーワード引数を辞書として受け取る

def my_sum(*args):
    return sum(args)

print(my_sum(1, 2, 3, 4))
# 10

print(my_sum(1, 2, 3, 4, 5, 6, 7, 8))
# 36
def func_kwargs(**kwargs):
    print('kwargs: ', kwargs)
    print('type: ', type(kwargs))

func_kwargs(key1=1, key2=2, key3=3)
# kwargs:  {'key1': 1, 'key2': 2, 'key3': 3}
# type:  <class 'dict'>
#ラーメン屋の関数
def ramen(soup, **option):
    price_soup = {"醤油":650, "塩":700, "味噌":720}#スープの指定は必須
    price = price_soup.get(soup, 0)

    #オプション(トッピング)
    if("noodle" in option):#麺の増量
        optprice = {"大盛":50, "特盛":100}
        price += optprice.get(option["noodle"], 0)

    price += option.get("egg", 0) * 70 #味玉1個70円
    price += option.get("meat", 0) * 50 #チャーシュー1枚増量50円
    return price

print(ramen("塩"))#700
print(ramen("醤油", noodle="大盛"))#700
print(ramen("味噌", egg=1, meat=2))#890
print(ramen("醤油", noodle="特盛", meat=6))#1050
print(ramen("塩", egg=2))#840
print(ramen("味噌", egg=1, rice=1))
rainit2006 commented 5 years ago

関数の引数

Pythonでは関数の引数はすべて参照渡しである。 参照渡しでも書き換え可能なオブジェクトと書き換え不可能なオブジェクトが存在する。

-- mutable object list, set, dict など -- immutable object int, float, str, tuple など

可以如下理解: 对于inmutable object 我们在函数参数传递是值传递 对于mutable object,我们在函数参数传递是指针传递

#-*- coding:utf-8 -*-
def calc(y):
    print("id(y):" + str(id(y)))
    y += 10
def main():
    x = 10
    print("id(x):" + str(id(x)))
    calc(x)
    print(x)

if __name__ == "__main__":
    main()

実行結果:
id(x):10106112
id(y):10106112
10

例2

def func(x):
    x[0]=4
    print(x)

x=[1]
func(x)
print(x)

结果:
[4]
[4]
rainit2006 commented 5 years ago

关于Python的调试: 使用 pdb 进行调试 http://python.jobbole.com/85668/ https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/00138683229901532c40b749184441dbd428d2e0f8aa50e000

rainit2006 commented 5 years ago

私有变量和私有方法

默认情况下,Python中的成员函数和成员变量都是公开的(public),在python中没有类似public,private等关键词来修饰成员函数和成员变量。 在python中定义私有变量只需要在变量名或函数名前加上 ”__“两个下划线,那么这个函数或变量就是私有的了。

在内部,python使用一种 name mangling 技术,将 membername替换成 _classnamemembername,也就是说,类的内部定义中, 所有以双下划线开始的名字都被"翻译"成前面加上单下划线和类名的形式。 例如:为了保证不能在class之外访问私有变量,Python会在类的内部自动的把我们定义的spam私有变量的名字替换成为 _classnamespam(注意,classname前面是一个下划线,spam前是两个下划线),因此,用户在外部访问spam的时候就会 提示找不到相应的变量。   python中的私有变量和私有方法仍然是可以访问的;访问方法如下: 私有变量:实例._类名__变量名 私有方法:实例._类名方法名()

其实,Python并没有真正的私有化支持,但可用下划线得到伪私有。   尽量避免定义以下划线开头的变量! (1)_xxx      "单下划线 " 开始的成员变量叫做保护变量,意思是只有类实例和子类实例能访问到这些变量, 需通过类提供的接口进行访问;不能用'from module import *'导入 (2)xxx    类中的私有变量/方法名 (Python的函数也是对象,所以成员方法称为成员变量也行得通。), " 双下划线 " 开始的是私有成员,意思是只有类对象自己能访问,连子类对象也不能访问到这个数据。 (3)xxx 系统定义名字,前后均有一个“双下划线” 代表python里特殊方法专用的标识,如 init__()代表类的构造函数。

rainit2006 commented 5 years ago

@staticmethod@classmethod方法 举例说明:

class A(object):
    def m1(self, n):
        print("self:", self)

    @classmethod
    def m2(cls, n):
        print("cls:", cls)

    @staticmethod
    def m3(n):
        pass

a = A()
a.m1(1) # self: <__main__.A object at 0x000001E596E41A90>
A.m2(1) # cls: <class '__main__.A'>
A.m3(1)

类中一共定义了3个方法,m1 是实例方法,第一个参数必须是 self(约定俗成的)。m2 是类方法,第一个参数必须是cls(同样是约定俗成),m3 是静态方法,参数根据业务需求定,可有可无。

一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法。 而使用@staticmethod或@classmethod,就可以不需要实例化,直接类名.方法名()来调用。 这有利于组织代码,把某些应该属于某个类的函数给放到那个类里去,同时有利于命名空间的整洁。