文章目錄
  1. 1. Python Study
    1. 1.1. Introduction
      1. 1.1.1. When
      2. 1.1.2. What
      3. 1.1.3. Why
    2. 1.2. IDE & Editor
    3. 1.3. Python Version Choosen
    4. 1.4. Useful Package
      1. 1.4.1. Pip
      2. 1.4.2. argparse
    5. 1.5. Tutorial(基础篇)
      1. 1.5.1. Introduction
        1. 1.5.1.1. Keywords and Identifier
        2. 1.5.1.2. Statements & Comments
        3. 1.5.1.3. Python I/O and Import
        4. 1.5.1.4. Python Operators
      2. 1.5.2. Flow Control
      3. 1.5.3. Function
        1. 1.5.3.1. Modules
        2. 1.5.3.2. Package
      4. 1.5.4. Datatypes
        1. 1.5.4.1. Basic Data Types
          1. 1.5.4.1.1. List
          2. 1.5.4.1.2. Tuple
          3. 1.5.4.1.3. Strings
          4. 1.5.4.1.4. Set
          5. 1.5.4.1.5. Dictionary
        2. 1.5.4.2. Conversion between data types
      5. 1.5.5. Files
        1. 1.5.5.1. File Operation
        2. 1.5.5.2. Directory
        3. 1.5.5.3. Exception
      6. 1.5.6. Object & Class
        1. 1.5.6.1. Name
        2. 1.5.6.2. Namepsace & Scope
        3. 1.5.6.3. Class
        4. 1.5.6.4. Inheritance
        5. 1.5.6.5. Operator Overloading
      7. 1.5.7. Iterator
      8. 1.5.8. Generator
      9. 1.5.9. Closure
      10. 1.5.10. Decorators
      11. 1.5.11. Property
      12. 1.5.12. RegEx
      13. 1.5.13. Date and Time
      14. 1.5.14. Process
    6. 1.6. Tips
      1. 1.6.1. encode and decode
      2. 1.6.2. main
      3. 1.6.3. Command Line Args
        1. 1.6.3.1. os.argv
        2. 1.6.3.2. argparse
      4. 1.6.4. Path
        1. 1.6.4.1. os.path
        2. 1.6.4.2. pathlib
      5. 1.6.5. Bat and Shell
    7. 1.7. Python GUI
      1. 1.7.1. TKinter
  2. 2. Reference
    1. 2.1. Conception Part
    2. 2.2. Tutorial Part
    3. 2.3. Other Part

Python Study

Introduction

When

Python is a widely used high-level programming language for general-purpose programming, created by Guido van Rossum and first released in 1991.)
Python第一版发布于1991年,由Guido van Rossum编写。

What

An interpreted language, Python has a design philosophy which emphasizes code readability (notably using whitespace indentation to delimit code blocks rather than curly brackets or keywords), and a syntax which allows programmers to express concepts in fewer lines of code than possible in languages such as C++ or Java.[22][23] The language provides constructs intended to enable writing clear programs on both a small and large scale.)
首先我们要知道Python跟Lua一样,是解释型语言(不需要编译,通过解析执行,有自己的解析器)。Python设计理念强调可读性(通过缩进而非{}来表示代码块)。

Python features a dynamic type system and automatic memory management and supports multiple programming paradigms, including object-oriented, imperative, functional programming, and procedural styles.)
Python是动态类型语言,同时有自己的内存管理机制,支持多种编程范式(待深入学习了解)。

Why

了解了Python When & What。那么我们Why什么要选择学习使用Python了?
Python is powerful… and fast; plays well with others; runs everywhere; is friendly & easy to learn; is Open.
supports multiple programming paradigms. It has a large and comprehensive standard library.[25])
把上面可以归纳如下:

  1. Run everywhere(跨平台)
  2. Friendly & easy to learn(学习更友好更容易(对于无编程经验的人更加友好,语法更nature))
  3. Supports multiple programming paradigms(支持多种编程范式)
  4. Large and comprehensive standard library(丰富的标准库和Package)

Note:
这里提一句Python里很有名的一句话:
“Life is short, you need python.”

IDE & Editor

学习任何一门编程语言,好的IDE或者Editor都能帮助我们更加快速的学习。
因为初学Python且Python是解析执行,这里暂时不考虑过于强大的IDE。
IDE详情选择可以参考Python IDE
这里通过使用Sublime Text 3以及其Python相关的扩展插件作为学习Python的Editor。
Sublime Text 3 Python相关插件设置详情

Python Version Choosen

Python有一个比较重要版本分割线2.x & 3.x。
详情参见Python2orPython3
这里就不深入去了解2.x和3.x之间的区别了。
简单的理解就是3.x提供了更多更全的功能支持,同时有更多的丰富的库支持。如果作为初学者,并不需要维护老版本(2.x)的工具代码时,完全可以从3.x学起。

Useful Package

Pip

Python有丰富的标准库。而其中最重要也是新手第一时间就应该安装的就是Pip。
Pip对于Python就好比Package Control好比Sublime Text 3。
Pip(Python Package Index)是一个Python Package集中管理安装的扩展包。
Pip安装详情参考官方文档
Pip安装成功后我们就可以通过Pip去查看或安装丰富的Python Package了。
Package Install:
PipPackageInstallation
Show Intalled Packages:
PipListInstalledPackages
安装之后的Package可以在安装目录查看到:
PythonPackageLocation
更多关于Pip使用查看官方文档

argparse

详细的介绍会在后面Tip的Command Line Args篇章

Tutorial(基础篇)

Introduction

Keywords and Identifier

Identifier(标识.e.g funcname, variable ……)定义规则:

  1. Keywords不能用做变量声明(这应该是任何语言都通用的规范了吧)
  2. 变量名不能以数字开头
  3. 变量名不能用特殊符号(e.g. !, @, #, $, %)
    简单了解下Python的关键词:
    PythonKeywords

Note:
Python is a case-sensitive language. This means, Variable and variable are not the same. Always name identifiers that make sense.
Python是大小写敏感的,大小写不同的变量名是不同变量。

Statements & Comments

Instructions that a Python interpreter can execute are called statements.
Python可解析执行的语句叫做Statements。
多行Statements可以通过\或者[]或者{}或者()链接或封装:

1
2
3
4
5
a = 1 + 2 + \
3 + 4 + \
5 + 6

b = (1 + 2 + 3 + 4)

Python设计理念强调可读性(通过缩进而非{}来表示代码块):
同时Python注释是通过# or ‘’’ or “””:

1
2
3
4
5
6
7
8
for i in range(5):
if i >= 5:
print("{0} >= 5".format(i))
break
else:
# No break happends in for loop
# Then execute this block
print("No number is equal or greater than 5!")

Docstring(Docstring is short for documentation string):
可以看出Docstring是一段文档描述(好比在C#里通过///编写描述信息一样)。Python在书写格式上要求比较严,虽然不会导致报错,但会算作不是规范的写法,这也就是我们为什么会去安装Sublime Text 3 flake8这样的linter插件了。

1
2
3
4
5
6
def addition(par1, par2):
"""This funtion is used to get result of (a + b)."""
return par1 + par2

print(addition(1, 2))
print(addition.__doc__)

DocString
可以看到我们定义了一个加法函数,并编写了docstring。
通过funcname._doc我们可以得到那段描述

Python I/O and Import

Python里的输入输出交互(好比C++里的cin,cout)是通过input和print。
因为需要交互所以需要在可执行Python代码的terminal里执行python脚本:
PythonInputAndOutput

因为Python的import是指import Module,我们需要知道Python里Module的定义,
Modules refer to a file containing Python statements and definitions.
Modules在Python里是指一个文件所包含的所有定义和声明(以文件为单位划分,文件名即为import的名字)。

在import Module还有一个重要的点就是,我们需要知道Python查找所有*.py的搜索路径(跟环境变量有点像):

1
print("sys.path:{0}".format(sys.path))

ImoprtSearchPath

我们可以指定只导入特定定义(e.g. from math import pi)

Note:
Python的Module和C#的namespace概念不一样,前者是以文件为单位,后者是以命名空间划分(支持在多个文件里定义在同一命名空间下)

Python Operators

运算符跟大多数编程差不多,这里只讲几个比较特殊的:
Logical Operators:

1
2
3
4
x = True
y = False
print(x and y)
print(x or y)

PythonLogicalOperator
或许跟Python提倡简洁明了有关,可以直接采用and or not之类的逻辑运算符

Identity operators:

1
2
3
4
5
6
7
8
9
x1 = 1
y1 = 1
print("x1 is y1 = ", x1 is y1)
y1 = 2
print("After y1 = 2. x1 is y1 = ", x1 is y1)

list1 = [1, 2, 3]
list2 = [1, 2, 3]
print("list1 is list2 = ", list1 is list2)

PythonIdentityOperator

Note:
is and is not are used to check if two values (or variables) are located on the same part of the memory.
List可以理解成分配了不同的内存去存储实际成员值所以是不同identity,上面x1 = 1和y1 = 1是located on the same part of the memory就需要理解后续会讲到的Namespaces概念

Membership operators:

1
2
3
list3 = [1, 'T', 'H']
print('T' in list3)
print(1 not in list3)

PythonMemberOperator

Note:
in & not in are used to test whether a value or variable is found in a sequence (string, list, tuple, set and dictionary).
in & not in 主要是用于判断特定变量或者值是否存在于特定sequence里。

Flow Control

if,elif,else,while,for这里主要记录一些Python相对于C++,C#,Java这些语言里的一些区别。

Python里是以:结束条件语句,以缩进表示层级。
while和for有一点比较特殊,支持else语句(没有break语句执行时)。

1
2
3
4
5
6
7
8
for i in range(5):
if i >= 5:
print("{0} >= 5".format(i))
break
else:
# No break happends in for loop
# Then execute this block
print("No number is equal or greater than 5!")

FlowControlForUsing

Function

Python的Function定义关键词是def,格式如下:

1
2
3
def func_name(paras):
"""Docstring"""
Statements

Python支持显示传递参数,也支持默认参数和不限数量参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# User-defined functions
def my_python_function(para1, dp1="dp1", dp2="dp2"):
"""My Python Function Docstring."""
# Build-in functions
print("my_python_function(para1:{0} dp1:{1} dp2:{2})".format(para1, dp1, dp2))

my_python_function("Tony")

# Keyword para call
my_python_function(dp1="ndp1", para1="Tang")


# Parameters without length limited
def arbitrary_para_function(*paras):
""" Python function without length of parameter limitation."""
for para in paras:
print(para)

arbitrary_para_function("para1", "para2", "para3")

PythonFunctionDefinition

Python也支持匿名函数(Lambda Function),只是不像C++,C#使用(x)=>表示而是lambda x:

1
2
sqrfunc = lambda x: x * 2
print(sqrfunc(2))

PythonAnonymousFunction

Modules

C,C++里有#include。C#有using。Java有import。Python里有Modules。
但Python里的Modules更像C,C++是针对文件为单位。
使用的时候通过import filename即可(也支持指定别名 as newname)

1
2
3
def my_first_python_func():
"""MyFirstPython.py's function."""
print("my_first_python_func() called")
1
2
3
import MyFirstPython as MFP

MFP.my_first_python_func()

PythonModuleImportAndUsing

知道了Python是以文件为单位导入的,那么我们也需要知道Python导入文件时的搜索路径(通过打印sys.path即可)

Note:
Python也支持只导入指定文件里的指定对象
e.g.

1
from math import pi

Package

C++,C#里有namespace。Java有package。Python里有Package(相当于Java里package和C#里namespace概念,负责抽象对应Directory到指定Package里)
Steps:

  1. 创建文件夹(文件夹名作为Package Name)
  2. 文件夹目录下创建一个init.py文件(默认可以不写任何内容)
  3. 通过import PackageName.Module引入特定文件
    e.g.
1
import MyPackage.MyFirstPython

PythonPackageUsing

Note:
Package是针对Directory而言,Module是针对file而言

Datatypes

Variable变量赋值在Python里简单明了:

1
2
3
p1 = 1
p2, p3, p4 = 2, 3, "Tony"
print(p1, p2, p3, p4)

判断数据类型Python是通过type()这个类似C#GetType()。
判断是否是某个类型实例Python是通过isinstance(),类似于Python里的is关键词。

1
2
3
4
5
6
7
8
9
10
11
class MyClass:
"""My first class."""

name

myclassinstance = MyClass()
myclassinstance.name = "Tony"
mystring = "Tony"
print(myclassinstance, " is typeof ", type(myclassinstance))
print("myclassinstance is typeof MyClass:", isinstance(myclassinstance, MyClass))
print(mystring, " is typeof ", type(mystring))

DataTypeCheck
可以看出在Python是弱语言类型,声明变量是无需显示指定变量类型。
同时通过type和isinstance可以判断实例对象类型。

Note:
这里的Data Type是指实例对象的类型,Python是弱类型语言。

Basic Data Types

Python支持大部分基本数据类型,e.g. int, float等。
有一点比较特殊的是Python支持complex numbers(复数):x + yj(x为实部,yj为虚部)

1
2
cn = 2 + 3j
print("cn = {0}".format(cn))

ComplexNumber
同时表示不同进制的Number只需添加不同前缀即可:
NumberSystem

List

List is an ordered sequence of items. It is one of the most used datatype in Python and is very flexible. All the items in a list do not need to be of the same type.
Python的List好比数组,但是更灵活,可存储不同类型的对象。

1
2
3
pythonList = [1, "a", 3.0, True]
for member in pythonList:
print(member, " is typof ", type(member))

PythonList

更多的List处理参见List.Method和其他Build-in Functions(比如len(),sorted()等)

Note:
List是通过[]定义。

Tuple

Tuple is an ordered sequence of items same as list.The only difference is that tuples are immutable. Tuples once created cannot be modified.
Tuple和List的唯一区别就是创建后不可再被改变,但如果内嵌可变的(e.g. List)那么List的数据是可以被改变的。Tuple是通过()定义内容。

1
2
3
4
5
6
my_tuple = (1, "string", [1, "th"])
my_tuple[2][0] = 2
for tuplemember in my_tuple:
print(tuplemember)
del my_tuple
# my_tuple -- Error: name 'my_tuple' is not defined

TupleUsing
从上面可以看出del关键词可以删除变量的引用。

Note:
Tuple是通过()定义。
Tuple相比List更适合用于存储固定的不同数据类型的数据。
Everything is object in Python.(这一点跟Java,C#一样)

Strings
1
2
3
4
mypythonstring = "我的名字是TonyTang"
print(mypythonstring)
print(mypythonstring[0])
mypythonstring[0] = '你'

PythonStrings

Note:
String is sequence of Unicode characters. Strings are immutable
Python里是采用Unicode编码存储字符串。Strings可以通过[]访问,但是不可被改变的。
We cannot delete or remove characters from a string. But deleting the string entirely is possible using the keyword del.因为string是immutable的,所以我们不能通过del删除string里面的个别character,但是我们可以删除对string的整个引用。

Set

Set is an unordered collection of unique items. Set is defined by values separated by comma inside braces { }. Items in a set are not ordered.
Set也是一系列数据的集合类型,但是是无序的。

1
2
3
mySet1 = {1, "a", 2, "b", 1}
for member in mySet1:
print("member in mySet1:{0}".format(member))

PythonSet
可以看出因为Set是无序的,连循环遍历出来的结果也是不确定的。所以针对Set,[]访问就是无意义也是不被允许的。

Every element is unique (no duplicates) and must be immutable (which cannot be changed).
Set还有一点特性就是成员是唯一且不可变的同时支持类似于集合与或等操作:

1
2
3
4
5
6
mySet2 = {"a", 2, "b"}
for member in (mySet1 & mySet2):
print("member in (mySet1 & mySet2):{0}".format(member))

for member in (mySet1 - mySet2):
print("member in (mySet1 - mySet2):{0}".format(member))

SetStudy

Note:
Set是通过{}定义。
更多操作参考Set.API

Dictionary

Dictionary is an unordered collection of key-value pairs.
Python里的Dictionary跟C#里的Dictionary差不多,代表无序的Key-Value主键值对。

1
2
3
myDictionary = {1: "Tony", "Tang": 2}
print(myDictionary[1])
print(myDictionary["Tang"])

PythonDictionary
可以看出Python里Dictionary的键值对定义时通过:分割,然后通过[]去方案对应Key得到Value值。

Note:
Dictionary是通过{}定义。
更多操作参考Dictionary.API

Conversion between data types

基础数据类型转换通过int,float,complex显示转换即可:

1
2
3
4
5
myint = int(2.5)
print(myint)
mylist = list('hello')
for member in mylist:
print(member)

PythonDataConversion

Files

File Operation

首先看看最新官方文档给出的API说明:
open(file, mode=’r’, buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

1
2
3
4
5
6
7
8
9
10
11
12
13
# try: finally: Make sure f close successfully
# specify encoding='utf-8' is used to avoid platform dependent problems
try:
f = open("./FilesFolder/TonyTangFile.txt", mode='r', encoding='utf-8')
for line in f:
print(line)
finally:
f.close()

# Another way to make sure file close successfully
with open("./FilesFolder/TonyTangFile.txt", mode='w', encoding='utf-8') as f:
# Do file operation here
f.write("Flow my heart!\nI have a dream!")

PythonFileOperation
从上面可以看到,open的几个关键参数,mode决定了可读还是可写等模式,encoding决定编码格式是为了确保不同平台脚本的一致性。

Directory

Python提供了os module支持很多文件夹目录操作的API

1
2
3
4
5
6
7
8
9
10
11
12
13
import os

print(os.getcwd())
print(os.listdir())
os.chdir("./FilesFolder")
print(os.getcwd())
if os.path.exists("MyNewFilesFolder") == False:
os.mkdir("MyNewFilesFolder")
print(os.listdir())
if os.path.exists("MyRenameFilesFolder") == True:
os.removedirs("MyRenameFilesFolder")
os.rename('MyNewFilesFolder', 'MyRenameFilesFolder')
print(os.listdir())

PythonDirectory
从上面可以看出Python的API都很简洁明了,跟bat,shell很像,具体使用过程中主要还是按需求差文档写自己的自动化即可。

Exception

Python Exception
Exception Handling
User-defined Exception

Object & Class

Name

Name (also called identifier) is simply a name given to objects.

1
2
3
4
5
6
7
8
9
10
11
a = 2
print('id(2) = ', id(2))
print('id(a) = ', id(a))

a = a + 1
print('id(a) = ', id(a))
print('id(3) = ', id(3))

b = 2
print('id(2) = ', id(2))
print('id(b) = ', id(b))

PythonNamespaceOutput
id()适用于打印object地址,从上面的输出可以看到只要Name指向Object的值是一致的,那么他们所指向的地址就是一致的。详情参考下图:
PythonName
This is efficient as Python doesn’t have to create a new duplicate object. This dynamic nature of name binding makes Python powerful; a name could refer to any type of object.

Note:
Everything in Python is an object.

1
import this

上面这段代码很有意思,会在控制台打印出Python的编程哲学:
TheZenOfPython

Namepsace & Scope

namespace is a collection of names.(前面讲解了什么是Name,接下来要理解的Namespace就好比一系列Name的集合)
我们平时用到的Build-in Functions就属于Build-in Namespace里。
让我们结合下图看看Python里Namespace的层级:
PythonNamespaceHierarchical

讲完Namespace,Python里还有一点跟Namespace密切相关的Scope:
Scope is the portion of the program from where a namespace can be accessed directly without any prefix.(Namespace在Python就好比C++,C#里的namespace。Scope就好比C++,C#里变量的有效区域。)

现阶段主要分为3中Scope:

  1. Scope of the current function which has local names(当前function scope)
  2. Scope of the module which has global names(全局scope)
  3. Outermost scope which has build-in names(最外层Build-in scope)

接下来透过实例学习理解Python里的Scope:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def outer_function():
"""Outer Function."""
a = 20

def inner_function():
"""Inner Function."""
global a
a = 30
print("a = ", a)

inner_function()
print("a = ", a)

a = 10
outer_function()
print("a = ", a)

PythonScope
可以看出在Function内的定义因为在不同的Scope不会覆盖Global Scope的a定义。当我们显示指定Function Scope里的a为global的a时,我们可以在Function Scope内引用到Global的a。

Class

接触过面向对象编程的人应该对Class都不陌生,他是我们抽象对象定义的关键类型。
在面向对象编程语言的Python里Class也起着同样的作用,只不过定义的方式有所区别,详情如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class MyFirstClass(object):
"""docstring for MyClass"""

def __init__(self, arg):
"""Class Constructor."""
super(MyFirstClass, self).__init__()
self.name = arg

def sayhi(self):
"""Class Member Function."""
print("Hello World!")

def printname(self):
"""Print name member."""
print("self.name = ", self.name)

# 这里因为我是定义在MyFirstPython.py文件里的,所以导入的是MyFirstPython
import MyFirstPython
mfp = MyFirstPython.MyFirstClass("Tony")
mfp.sayhi()
mfp.printname()
print(mfp.name)
mfp.age = 10
print(mfp.age)
del mfp.name
# mfp.printname() AttributeError: 'MyFirstClass' object has no attribute 'name'
del mfp
# mfp.sayhi() NameError: name 'mfp' is not defined

PythonClassDefinition
从上面可以看出Python里Class的定义格式如下:

1
2
3
4
5
6
7
8
9
def classname(父类):
"""Docstring Class description."""
def __init__(self,arg):
"""Docstring Constructor description."""
# constructor's body

def functionname(arg):
"""DocString Member Function description."""
# body

init就好比C++里的构造函数。
Python里的继承写法:classname()括号里面跟的是父类,在子类可以通过super去访问父类。
值得一提的是Docstring,每一个类或者方法都有Docstring,我们可以通过classname.doc的方式去访问。
同时我们看到Python里还可以在运行时动态定义成员变量(e.g. mfp.age)
Python里不是通过new关键词去实例化类对象,但del关键词就好比C++里和new配对的delete,但这里的delete不仅是针对new出来的实例化对象进行回收,还能针对特定实例化成员进行删除。(当我们del mfp实例对象时,我们只是把mfp的对于Object的引用从corresponding namespace里移除而非真的销毁内存里Object。真正的销毁是发生在没有人在绑定到该Object时。)

This automatic destruction of unreferenced objects in Python is also called garbage collection.(真正的销毁就好比C++里的GC对内存进行释放)

Note:
Python is an object oriented programming language.

Inheritance

Like C++, a class can be derived from more than one base classes in Python. This is called multiple inheritance.

关于继承这里就不多讲了,大家参考文档介绍。

Operator Overloading

Operator Overloading翻译过来应该是运算符重载。

在了解Operator Overloading之前,让我们来了解下Python Class里的一些特殊方法。

这里的特殊方法学过lua的同学应该会感到很亲切:

  1. new — New一个Class的实例对象时会被调用
  2. init — Class的构造函数(父类构造函数需要手动调用,默认不递归调用)
  3. del — Class实例对象销毁时调用(类似C#析构函数)
  4. class — 访问类的静态变量的时候(实例对象可以直接通过self访问)
  5. str — str(),format()以及print()函数触发Class获取字符串表达方法
  6. lt — <运算符操作时调用
  7. le — ==运算法操作时调用
  8. hash — hash()方法计算Class实例对象Hash值时
  9. getattr — 访问Class成员不能存在时调用(类似Lua的__index元方法)
  10. setattr — 设置Class成员值时调用(类似Lua的__newindex元方法)
  11. ……

更多特殊方法参考:Special method names

从上面可以看出Python和Lua有很多相似的地方。

接下来让我们看看实战效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# MyFirstPython.py
# File Name: MyFirstPython.py
# Description: This file is used to study python
# Author: TangHuan
# Create Date: 2017/6/5

import shutil

class MyFirstClass(object):
"""docstring for MyClass"""
# class Static Member
age = 10

# 构造函数
def __init__(self, name):
"""Class Constructor."""
super().__init__()
print("MyFirstClass:__init__({})".format(name))
self.name = name

# str(),format()以及print()函数触发
def __str__(self):
return "MyFirstClass name:{} age:{}".format(self.name, self.age)

# 获取不存在成员时触发
def __getattr__(self, name):
print("MyFirstClass:__getattr__({}) not exist!".format(name))

# 设置成员值时触发
def __setattr__(self, name, value):
super().__setattr__(name, value)
print("MyFirstClass:__setattr__({}, {})!".format(name, value))

# 加号运算符重载
def __add__(self, other):
newName = self.name + other.name
return MyFirstClass(newName)

def sayhi(self):
"""Class Member Function."""
print("MyFirstClass:sayhi() Hello World!")

def printname(self):
"""Print name member."""
print("MyFirstClass:printname() self.name = ", self.name)


def my_first_python_func():
"""MyFirstPython.py's function."""
print("my_first_python_func() called")
1
2
3
4
5
6
7
8
9
10
11
12
13
# Class e.g.
mfp = MyFirstPython.MyFirstClass("Tony")
print(mfp.__class__.age)
mfp.sayhi()
mfp.printname()
print(mfp.name)
print(mfp.noneexitname)
mfp.age = 10
print(mfp.age)
print(mfp)
mfp2 = MyFirstPython.MyFirstClass("Tang")
tempMfp = mfp + mfp2
print(tempMfp)

ClassSpecialFunctionsOutput

通过上面的学习用例,可以看到我们通过自定义init,str,getattr,setattr,add等特殊方法实现了类构造,类成员自定义访问设置,类+运算符重载,类print()等方法自定义输出等效果。看到这里,不得不说Python特殊方法和Lua的元方法概念很像。

Iterator

Iterator in Python is simply an object that can be iterated upon. An object which will return data, one element at a time.

这里的Iterator和C#里的迭代器应该是一个概念。实现迭代器需要实现两个特殊方法(iternext)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File Name: 		IteratorStudy.py
# Description: This file is used to study python iterator
# Author: TangHuan
# Create Date: 2021/5/25

# 迭代器类
class IteratorClass(object):
"""Class to implement an iterator"""

# 构造函数
def __init__(self, max):
super().__init__()
self.max = max

# 返回迭代器
def __iter__(self):
print("IteratorClass:__iter__()")
self.n = 0
return self

# 迭代器MoveNext
def __next__(self):
print("IteratorClass:__next__()")
if self.n <= self.max:
value = self.n
self.n += 1
return value
else:
raise StopIteration

iteratorClassInstance = IteratorClass(5)
for iter in iteratorClassInstance:
print(iter)

IteratorOuput

Generator

Python generators are a simple way of creating iterators. Simply speaking, a generator is a function that returns an object (iterator) which we can iterate over (one value at a time).

It is fairly simple to create a generator in Python. It is as easy as defining a normal function, but with a yield statement instead of a return statement.

看介绍Generators的概念和C#的携程差不多。

Generator和普通方法的区别:

  1. Generator function contains one or more yield statements.
  2. When called, it returns an object (iterator) but does not start execution immediately.
  3. Methods like __iter__() and __next__() are implemented automatically. So we can iterate through the items using next().
  4. Once the function yields, the function is paused and the control is transferred to the caller.
  5. Local variables and their states are remembered between successive calls.
  6. Finally, when the function terminates, StopIteration is raised automatically on further calls.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Generator
GeneratorVariable = 0
def GeneratorFunction():
global GeneratorVariable
print("GeneratorFunction() {}".format(GeneratorVariable))
yield GeneratorVariable
GeneratorVariable += 1
print("GeneratorFunction() {}".format(GeneratorVariable))
yield GeneratorVariable
GeneratorVariable += 1
print("GeneratorFunction() {}".format(GeneratorVariable))
yield GeneratorVariable

GeneratorFunc = GeneratorFunction()
print("GeneratorFunction Start")
for generator in GeneratorFunc:
print(generator)

GeneratorOuput

可以看到Generator在Python里还能直接通过for循环的形式便利这一点和C#的携程还不太一样。

通过Generator我们可以简化自定义Iterator的写法,无需自定义iternext方法,通过自定义的Generator方法即可实现迭代效果。Generator更多好处参考:Generator

Closure

Closure指类似传统语言里的闭包,但在Python里有几个较大的区别:

  1. 闭包访问外围变量时,默认是只读的,需要通过nonlocal关键字来标识闭包内部可写。
  2. 闭包必须是嵌套函数定义
  3. 嵌套函数必须访问外部成员
  4. 外围函数必须返回嵌套函数自身

Python里用闭包的好处:

Closures can avoid the use of global values and provides some form of data hiding. It can also provide an object oriented solution to the problem.

Decorators

A decorator takes in a function, adds some functionality and returns it.

看介绍Decorator像是设计模式里的修饰器概念,能够做到给现有功能添加额外功能的作用。

看介绍利用万物皆object的概念(类似Lua里第一类值)的概念,实现封装函数调用实现扩展函数功能。

还有更多更复杂的使用方式,详情参考:Decorators

Note:

  1. everything in Python (Yes! Even classes), are [objects].

Property

Property类似于C#里的属性概念。Python通过关键字@property实现属性的快速定义。

PropertyKeywordDefinition

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File Name: 		PropertyStudy.py
# Description: This file is used to study python property
# Author: TangHuan
# Create Date: 2021/5/25

# 属性类
class PropertyClass(object):
"""Class to implement an property"""

# 构造函数
def __init__(self, propertyvalue):
super().__init__()
print("PropertyClass.__init__()")
self.Property = propertyvalue

@property
def Property(self):
print("Getting Property Value : {}".format(self._Property))
return self._Property

@Property.setter
def Property(self, value):
print("Setting Property Value : {}".format(value))
self._Property = value

propertyClassInstance = PropertyClass(5)
print(propertyClassInstance.Property)
propertyClassInstance.Property = 10
print(propertyClassInstance.Property)

PropertyOutput

更多学习参考:[Property][https://www.programiz.com/python-programming/property]

RegEx

Date and Time

Process

multiprocessing is a package that supports spawning processes using an API similar to the threading module.

threading module constructs higher-level threading interfaces on top of the lower level _thread module.

The subprocess module allows you to spawn new processes, connect to their input/output/error pipes, and obtain their return codes. This module intends to replace several older modules and functions:os.system os.spawn*

从介绍可以看出,multiprocessing包是用于支持多进程类似多线程功能的模块。

threading是多线程的一个上层抽象模块。

multiprocessing是多进程的一个上层抽象模块(相比threading,不受限于Global Interpreter Lock(多线程锁,限定同时只有一个Thread执行)可以真正利用多核来跑多进程功能。

subprocess模块是封装的更好的一个创建使用子进程的模块,同时提供了和子进程处理交互相关的接口。

这里我们重点学习process相关即multiprocessing和subprocess相关概念和使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
File Name: MultiProcessStudy.py
Description: This file is used to study python subprocess
Author: TangHuan
Create Date: 2021/8
"""


import os
import subprocess
import time
import random
from multiprocessing import Pool

def process_task(subProcessName):
print("subProcessName:{0} Process pid:{1}".format(subProcessName, os.getpid()))
start = time.time()
time.sleep(random.random())
end = time.time()
print("SubProcess:{0} Process pid:{1} runs:{2} seconds!".format(subProcessName, os.getpid(), end - start))

if __name__=='__main__':
print("MultiProcessStudy")
# 打印主进程id
print("Current Process pid:{0}".format(os.getpid()))

# 创建4个多进程(子进程)的进程池
p = Pool(4)
for i in range(5):
p.apply_async(process_task, args=("SubProcess{0}".format(i),))
print("Waiting for all subprocesses done.")
# 停止提交更多的任务到p里
p.close()
# 等待p里的所有子线程任务完成
p.join()
print("All subprocesses done.")

# SubProcess的方式开启子进程1
subProcess1 = subprocess.Popen(['python', 'SubProcess1.py'])
print("start SubProcess1")
# SubProcess的方式开启子进程2
subProcess2 = subprocess.Popen(['python', 'SubProcess2.py'])
print("start SubProcess2")
# 等待子进程1完成
subProcess1.wait()
print("SubProcess1 complete")
# 等待子进程2完成
subProcess2.wait()
print("SubProcess2 complete")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# File Name: 		SubProcess1.py
# Description: This file is used to study python subprocess
# Author: TangHuan
# Create Date: 2021/8/7

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

import os
import time

print("SubProcess1-1")

print("SubProcess1 parent pid:{0}".format(os.getppid()))
print("SubProcess1 pid:{0}".format(os.getpid()))
time.sleep(1)
print("SubProcess1-2")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# File Name: 		SubProcess2.py
# Description: This file is used to study python subprocess
# Author: TangHuan
# Create Date: 2021/8/7

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

import os
import time

print("SubProcess2-1")

print("SubProcess2 parent pid:{0}".format(os.getppid()))
print("SubProcess2 pid:{0}".format(os.getpid()))
time.sleep(1)
print("SubProcess2-2")

MultiProcessingOutput

从上面的测试代码可以看出,我们通过mutilprocessing模块提供的Pool(用于控制一组子进程的创建使用)成功创建了4个多进程池开启5个多进程任务(其中有一个任务需要等待一个可用的进程才能执行)。

通过SubProcess模块,我们实现了开启多个进程执行不同Python脚本的功能,从而实现多进程执行多Python脚本任务的需求。

更多更细节的学习参考:

多进程

Note:

  1. multiprocessing和subprocess是提供了多进程而非多线程
  2. Unix/Linux操作系统多进程是采用fork()实现真正的进程复制,而Windows不支持fork()函数,Windows上多进程是通过在子进程里创建新的Python解析器来实现的(来源:On Windows, there is no such system call. Python needs to perform the quite heavy task of creating a fresh Python interpreter session in the child, and re-create (step by step) the state of the parent.),所以我们执行多进程时要通过命令行而非Sumblime等软件。

待续……

Tips

encode and decode

字符编码问题,无论是shell,python都是需要考虑的,不然会出现乱码的情况。

encode(编码)和decode(解码)是需要一一对应的,不然同一个二进制数据,通过不同的编码和解码会得出不一样的结果。

首先我们来看看Python官网对于Encode和Decode的介绍:
Strings are stored internally as sequences of code points in range 0x0–0x10FFFF. (See PEP 393 for more details about the implementation.) Once a string object is used outside of CPU and memory, endianness and how these arrays are stored as bytes become an issue. As with other codecs, serialising a string into a sequence of bytes is known as encoding, and recreating the string from the sequence of bytes is known as decoding.

从上面可以看出,我们的string最终都是以字节码形式存储起来的。我们指定如何编码字符串到字节码的方法叫做编码。我们制定如何解析字节码到字符串的方法叫做解码。

关于字符编码的详细学习,这里参考以前转载的一片文章来加深理解:
关于字符编码,你所需要知道的(ASCII,Unicode,Utf-8,GB2312…)

不难看出,编码和解码方式要是不一致,最终字节码数据解析出来就会出现不正确(比如乱码)的情况。

这里需要提一下Python 3.X里有提供codecs的Package专门负责处理encode,decode问题。
codecs深入了解链接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/usr/bin/python
# -*- coding: utf-8 -*-
# 指定文件包含非anscii字符

import sys
import codecs

# 打印系统默认编码
print(sys.getdefaultencoding())

# 如果默认编码不是utf-8,强制设置成utf8去支持文本内非anscii字符
# 下面这段代码针对Python 2.X
# Phtyon 3.X默认就是utf-8编码不需要自己设定utf-8编码
#reload(sys)
#sys.setdefaultencoding('utf-8')

s="English-中文"
print(s)

s2=codecs.encode(s,"gb2312")
print(codecs.decode(s2,"gb2312"))
#解码格式与编码格式gb2312不一致,报错,无法解析
#print(codecs.decode(s2,"utf-8"))

# 需要指定和文件一样的编码格式才能正确解析文件里的内容
# 读取解码格式与inputfile.txt保存的编码格式utf-8不一致报错
#f = open('inputfile.txt','r',encoding='gb2312')
f = open('inputfile.txt','r',encoding='utf-8')
content = f.read()
print(content)

EncodeAndDecode

可以看到当我们把通过gb2312编码的字符串通过对应的gb2312解析时能正确显示,但用utf-8去解析时就出现了问题。同理文件读取指定的解码格式与文件自身的编码格式不一致也会出现无法读取的情况。

结论:
编码和解码格式要一一对应才能正确解析显示。
String is sequence of Unicode characters. Strings are immutable. We cannot delete or remove characters from a string. But deleting the string entirely is possible using the keyword del.
Python里是采用Unicode编码存储字符串。Strings可以通过[]访问,但是不可被改变的。
因为string是immutable的,所以我们不能通过del删除string里面的个别character,但是我们可以删除对string的整个引用。

main

'__main__' is the name of the scope in which top-level code executes. A module’s name is set equal to '__main__' when read from standard input, a script, or from an interactive prompt. A module can discover whether or not it is running in the main scope by checking its own __name__, which allows a common idiom for conditionally executing code in a module when it is run as a script or with python -m but not when it is imported:

从上面的介绍可以看出main表示是否是从最上层执行(比如直接执行脚本,命令行执行脚本)代码的名字。

如何判定是否是从最上层执行当前python脚本了?

从上面的介绍可以看出,name变量标识了当前python脚本是通过什么方式执行的。

1
2
3
4
5
6
7
# File Name: 		MainName.py
# Description: This file is used to study __name__ and __main__ using
# Author: TangHuan
# Create Date: 2021/5/22

print("MainName.py")
print(__name__)

比如上面这段代码,在通过脚本直接执行时,我们会看到打印输出:

DirectExecuteNameOuput

如果我们通过以下代码导入MainName.py会看到打印输出:

1
import MyPackage.MainName

ImportNameOutput

在命令行执行脚本和直接执行脚本同理。

可以看出当我们通过非import方式导入脚本时,name的值为main这个特殊的值,我们可以通过判定这个值来判定当前python脚本的执行方式,因此我们经常会看到以下代码:

1
2
if __name__ == "__main__":
print("DoSomething()")

这样就能做到只有通过非import方式执行当前python脚本时才执行某些东西。

Command Line Args

os.argv

很多时候作为脚本语言Python,我们写的Python脚本更多是用于自动化流程(比如打包签包等),而调用此Python脚本的方式大多为命令行调用。这里就引出了如何通过命令行将我们所需的参数传递进我们Python脚本的问题。

Python自带了一个os.argv的参数用于获取命令行传入参数数据。

1
2
for arg in sys.argv:
print(arg)

如果我们通过命令执行以下脚本传入参数:

1
***.py param1 param2 param3

我们会看到以下输出:

PythonArgsOutput

可以看到第0个参数表示当前python脚本执行的文件路径。

但上面这种方式,虽然能获得命令行传入的参数,但对于参数的格式以及参数的要求对于用的人来说都还是不透明且未做任何安全检查也未给与任何提示信息的,这样会导致Python脚本内部还需要自行做这些参数检查。这里就要引出接下来要提到的模块功能:argparse

Note:

  1. 如果以-c的参数触发python,os.argv的第一个参数是-c,详情参考:-c

argparse

The argparse module makes it easy to write user-friendly command-line interfaces. The program defines what arguments it requires, and argparse will figure out how to parse those out of sys.argv. The argparse module also automatically generates help and usage messages and issues errors when users give the program invalid arguments.

argparse是Python里帮助我们引导输入参数和快速解析参数的模块。

接下来我们直接上学习Demo,简单学习了解下如何使用argparse帮助我们快速引导输入参数和快速解析参数:
argparsestudy.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/usr/bin/python
# -*- coding: utf-8 -*-
# 指定文件包含非anscii字符

import os
import argparse
import sys

# argparse解析参数输入,需要先定义一个ArgumentParser对象
# description - -h的时候显示在最前面的信息
parser = argparse.ArgumentParser(description='Study argparse module.')

# add_argument - 定义如何解析一个参数
# 第一个参数代表参数名
# type - 指定参数数据类型
# help - -h时解释该参数的用意
# dest - 表示该参数最终在parser.parse_args()返回对象里的名字
# default - 表示该参数的默认值
# required - 表示该参数是不是必须填的参数
parser.add_argument('--APKName', type=str,
help='APK名字', dest='APKName',
required=True)

parser.add_argument('--ClientChId', type=str,
help='新的ClientChId值', dest='New_Clientchid',
default='com.default.com')

parser.add_argument('--LEBIAN_VERCODE', type=int,
help='新的LEBIAN_VERCODE值', dest='New_Lebian_Vercode',
default='0')

parser.add_argument('--TemplateValue', type=str,
help='替换AndroidManifest.xml里quicksdk_packName字段为新的*', dest='NewTemplateValue',
default='com.defaulttemplatevalue.com')

parser.add_argument('--ResourcePath', type=str,
help='放入新资源到指定包内目录', dest='NewResourcePath',
default='./default.aba')

# 解析输入的参数
args = parser.parse_args()

# 打印参数的详细信息,通过访问parser.parse_args()的对象去访问
print(args)
print("APKName : {0}".format(args.APKName))
print("New_Clientchid : {0}".format(args.New_Clientchid))
print("New_Lebian_Vercode : {0}".format(args.New_Lebian_Vercode))
print("NewTemplateValue : {0}".format(args.NewTemplateValue))
print("NewResourcePath : {0}".format(args.NewResourcePath))

命令行输入:
Python .\argparsestudy.py -h
会看到每个参数的详细信息
ArgparseHelpInfo

真正使用时因为—APKName是必传参数,所以按下面方式调用即可:
Python .\argparsestudy.py —APKName com.tonytang.com
ArgparseUsing
可以看到我们通过argparse模块轻松的完成参数输入引导以及参数解析的任务。

更多详细学习参考:
argparse — Parser for command-line options, arguments and sub-commands

Path

关于Path模块,这里需要先了解一下跟语言无关的一个基础知识。

路径中斜杠/和反斜杠\的区别

从博客介绍中可以看出,斜杠和反斜杠主要是Windows路径和Unix路径里区分,大部分情况(无论是浏览器还是html url都是反斜杠)。

这里就引出了在自动化流程里涉及路径时,我们需要兼容Windows,Mac,Android或者IOS时候路径问题需要处理。而Path模块正是能够处理这一问题的现有模块功能。

os.path

这里只是简单示范几个常规API用法,详情参考:os.path

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import os
import sys

FilePath = sys.argv[0]
print("FilePath = {}".format(FilePath))

# 获取当前工作目录
WorkingFolder = os.getcwd()
print("WorkingFolder = {}".format(WorkingFolder))

# 文件所在文件夹名
FileFolderName = os.path.dirname(FilePath)
print("FileFolderName = {}".format(FileFolderName))

if os.path.isdir(WorkingFolder):
print("{} is directory!".format(WorkingFolder))
else:
print("{} is not directory!".format(WorkingFolder))

OSPathAPIOutput

pathlib

This module offers classes representing filesystem paths with semantics appropriate for different operating systems. Path classes are divided between pure paths, which provide purely computational operations without I/O, and concrete paths, which inherit from pure paths but also provide I/O operations.

上面提到了两种概念PurePath和Concrete Paths,前者只是提供路径概念(比如区分Windows还是Unix文件系统以及路径相关操作)不和文件系统挂钩。后者就是Pathlib提供的OOP文件路径系统抽象,提供了一系列的文件操作接口(Pathlib相当于进阶版的Path抽象模块)。

UMLPathDesgin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import os
import sys
from pathlib import Path

FilePath = sys.argv[0]
print("FilePath = {}".format(FilePath))

# 获取当前工作目录
WorkingFolder = os.getcwd()
print("WorkingFolder = {}".format(WorkingFolder))

# 文件所在文件夹名
FileFolderName = os.path.dirname(FilePath)
print("FileFolderName = {}".format(FileFolderName))

if os.path.isdir(WorkingFolder):
print("{} is directory!".format(WorkingFolder))
else:
print("{} is not directory!".format(WorkingFolder))

# 这一步可以自动转化成对应平台的路径格式(最后需要str的时候需要转化成str)
PathWorkingFolder = Path(WorkingFolder)
print("PathWorkingFolder = {}".format(PathWorkingFolder))

WorkingFolderJoinPath = PathWorkingFolder.joinpath("joinpath")
print("WorkingFolderJoinPath = {}".format(WorkingFolderJoinPath))

if PathWorkingFolder.exists():
print("{} exists!".format(PathWorkingFolder))

PathLibAPIOutput

这里用Pathlib除了他提供了更多的文件路径操作外,还有就是它继承了PurePath跨平台文件路径处理的特性,让我们可以在处理文件路径时无需关心平台。

Bat and Shell

Bat和Shell在Unity自动化&IOS自动化签包文章中已经了解过了,这里主要是介绍如何在python里和bat,shell交互(比如我们想获取环境变量里的数据,执行shell命令等)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import os

androidhome = os.getenv("ANDROID_HOME")
if androidhome == None:
print("未配置ANDROID_HOME环境变量路径,请先配置ANDROID_HOME环境变量")
else:
print("ANDROID_HOME = {}".format(androidhome))

WorkingFolder = os.getcwd()
print("WorkingFolder = {}".format(WorkingFolder))

CmdCommand = "echo Hello World"
print("CmdCommand = {}".format(CmdCommand))
# 执行CDM命令
os.system(CmdCommand)

# 确保不自动关闭
input("请按任意键继续...")

SystemInfoOutput

注释和用法都很详细了,这里就不多介绍了。

Python GUI

GUI(Graphic User Interface)可视化用户界面。
Python实现GUI有很多选择,这里参考一位博主的分享:
Python 的图形界面(GUI)编程?

学习需要从需求出发,这里本人主要是想用Python写点简单的GUI来满足可视化即可,所以对GUI要求不高,本人不是以Python为主,只是用Python写点周边小工具,所以这里本人考虑的是学习了解Python自带的TKinter。

如果对GUI要求比较高,有比较常用Python,根据上面那位博主的建议来看,PyQT是个不错的选择。

TKinter

官方介绍:
Tkinter is Python’s de-facto standard GUI (Graphical User Interface) package. It is a thin object-oriented layer on top of Tcl/Tk.

接下来将根据Tkinter 8.5 reference: a GUI for Python去学习了解TKinter的概念以及使用。

待续……

Reference

Conception Part

Python
Guido van Rossum

Tkinter

Encode and Decode in Python

Tutorial Part

Python Tutorial
Python Package Index

Tkinter 8.5 reference: a GUI for Python

codecs

argparse

Python教程

Other Part

Python2orPython3
Python 的图形界面(GUI)编程?

文章目錄
  1. 1. Python Study
    1. 1.1. Introduction
      1. 1.1.1. When
      2. 1.1.2. What
      3. 1.1.3. Why
    2. 1.2. IDE & Editor
    3. 1.3. Python Version Choosen
    4. 1.4. Useful Package
      1. 1.4.1. Pip
      2. 1.4.2. argparse
    5. 1.5. Tutorial(基础篇)
      1. 1.5.1. Introduction
        1. 1.5.1.1. Keywords and Identifier
        2. 1.5.1.2. Statements & Comments
        3. 1.5.1.3. Python I/O and Import
        4. 1.5.1.4. Python Operators
      2. 1.5.2. Flow Control
      3. 1.5.3. Function
        1. 1.5.3.1. Modules
        2. 1.5.3.2. Package
      4. 1.5.4. Datatypes
        1. 1.5.4.1. Basic Data Types
          1. 1.5.4.1.1. List
          2. 1.5.4.1.2. Tuple
          3. 1.5.4.1.3. Strings
          4. 1.5.4.1.4. Set
          5. 1.5.4.1.5. Dictionary
        2. 1.5.4.2. Conversion between data types
      5. 1.5.5. Files
        1. 1.5.5.1. File Operation
        2. 1.5.5.2. Directory
        3. 1.5.5.3. Exception
      6. 1.5.6. Object & Class
        1. 1.5.6.1. Name
        2. 1.5.6.2. Namepsace & Scope
        3. 1.5.6.3. Class
        4. 1.5.6.4. Inheritance
        5. 1.5.6.5. Operator Overloading
      7. 1.5.7. Iterator
      8. 1.5.8. Generator
      9. 1.5.9. Closure
      10. 1.5.10. Decorators
      11. 1.5.11. Property
      12. 1.5.12. RegEx
      13. 1.5.13. Date and Time
      14. 1.5.14. Process
    6. 1.6. Tips
      1. 1.6.1. encode and decode
      2. 1.6.2. main
      3. 1.6.3. Command Line Args
        1. 1.6.3.1. os.argv
        2. 1.6.3.2. argparse
      4. 1.6.4. Path
        1. 1.6.4.1. os.path
        2. 1.6.4.2. pathlib
      5. 1.6.5. Bat and Shell
    7. 1.7. Python GUI
      1. 1.7.1. TKinter
  2. 2. Reference
    1. 2.1. Conception Part
    2. 2.2. Tutorial Part
    3. 2.3. Other Part