最近在看机器学习相关的东西,Python有点生疏了,简单复习一下。
(*号表示有待补充)
参加来源:Learn X in Y minutes、菜鸟教程
在Python3中要注意“/”和“//”的区别,“/”是正常除,“//”是取整除
Python支持乘方运算
Python中的逻辑运算用首字母大写的True和False表示真和假(底层还是1和0)。用and表示与操作,or表示或操作,not表示非操作。而不是C++或者是Java当中的&&, || 和!。
优先级:not > and > or
python的字符串支持+拼接操作,单引号和双引号都表示字符串
# Strings are created with " or '
"This is a string."
'This is also a string.'
# Strings can be added too! But try not to do this.
"Hello " + "world!" # => "Hello world!"
用len()来计算字符串长度,也可以使用[]来访问单个字符
# A string can be treated like a list of characters
"This is a string"[0] # => 'T'
# You can find the length of a string
len("This is a string") # => 16
在Python中None也是一个对象,所有的None都指向同一个对象
# None is an object
None # => None
# Don't use the equality "==" symbol to compare objects to None
# Use "is" instead. This checks for equality of object identity.
"etc" is None # => False
None is None # => True
如果要判断一个值为空,可以用**bool()**函数,只要是空值都会返回False
# None, 0, and empty strings/lists/dicts/tuples all evaluate to False.
# All other values are True
bool(None)# => False
bool(0) # => False
bool("") # => False
bool([]) # => False
bool({}) # => False
bool(()) # => False
输出是print,输入用input,在input()中传入字符串参数,会被当做提示输出:
a = [1, 2, 3, 4] # Point a at a new list, [1, 2, 3, 4]
b = a # Point b at what a is pointing to
b is a # => True, a and b refer to the same object
b == a # => True, a's and b's objects are equal
b = [1, 2, 3, 4] # Point b at a new list, [1, 2, 3, 4]
b is a # => False, a and b do not refer to the same object
b == a # => True, a's and b's objects are equal
在list末尾插入删除元素
# Add stuff to the end of a list with append
li.append(1) # li is now [1]
li.append(2) # li is now [1, 2]
li.append(4) # li is now [1, 2, 4]
li.append(3) # li is now [1, 2, 4, 3]
# Remove from the end with pop
li.pop() # => 3 and li is now [1, 2, 4]
# Let's put it back
li.append(3) # li is now [1, 2, 4, 3] again.
删除中间的元素可以用del或者remove()
# Remove arbitrary elements from a list with "del"
del li[2] # li is now [1, 2, 3]
# Remove first occurrence of a value
li.remove(2) # li is now [1, 3]
li.remove(2) # Raises a ValueError as 2 is not in the list
插入元素用insert()
# Insert an element at a specific index
li.insert(1, 2) # li is now [1, 2, 3] again
如果要将两个list合并,可以用**+或者extend()**
li + other_li # => [1, 2, 3, 4, 5, 6]
# Concatenate lists with "extend()"
li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6]
判断元素第一次出现的位置用index(),要判断list中是否包含某个元素,用in关键字
li.index(2) # => 1
li.index(4) # Raises a ValueError as 4 is not in the list
# Check for existence in a list with "in"
1 in li # => True
要注意list的切片操作是左闭右开的区间,如果要获得逆序可以使第三个参数为-1
# You can look at ranges with slice syntax.
# The start index is included, the end index is not
# (It's a closed/open range for you mathy types.)
li[1:3] # Return list from index 1 to 3 => [2, 4]
li[2:] # Return list starting from index 2 => [4, 3]
li[:3] # Return list from beginning until index 3 => [1, 2, 4]
li[::2] # Return list selecting every second entry => [1, 4]
li[::-1] # Return list in reverse order => [3, 4, 2, 1]
# Use any combination of these to make advanced slices
# li[start:end:step]
tuple 和 list 不同的是,前者使用 () 进行初始化,且tuple是不可变的(但是tuple中的可变元素依旧可变,如list)
# Tuples are like lists but are immutable.
tup = (1, 2, 3)
tup[0] # => 1
tup[0] = 3 # Raises a TypeError
大部分list的操作,tuple也支持,如 len()、+、切片、in
dict的作用和map类似,存储key和value的键值对,用 {} 表示dict
如
# Dictionaries store mappings from keys to values
empty_dict = {}
# Here is a prefilled dictionary
filled_dict = {"one": 1, "two": 2, "three": 3}
两种获取value 的方法
# Look up values with []
filled_dict["one"] # => 1
filled_dict.get('one') #=> 1
如果要获取所有key或是value的list,可以用如下方法,但注意在python3.7以前顺序和插入顺序是不同的
list(filled_dict.keys()) # => ["three", "two", "one"] in Python <3.7
list(filled_dict.keys()) # => ["one", "two", "three"] in Python 3.7+
list(filled_dict.values()) # => [3, 2, 1] in Python <3.7
list(filled_dict.values()) # => [1, 2, 3] in Python 3.7+
用setdefault() 方法来插入不存在的键值对,用update() 方法来更新值
filled_dict.setdefault("five", 5) # filled_dict["five"] is set to 5
filled_dict.setdefault("five", 6) # filled_dict["five"] is still 5
# Adding to a dictionary
filled_dict.update({"four":4}) # => {"one": 1, "two": 2, "three": 3, "four": 4}
filled_dict["four"] = 4 # another way to add to dict
如果要删除,可以使用del
dict4 = {'name': 'Tom', 'age': 18}
del dict4['name'] # 删除字典,如果键不存在,返回错误
print(dict4)
del dict4 # 删除整个字典
print(dict4)
(关于dict的删除有四种方法,详见Python字典删除键值对和元素的四种方法)
set和c++中的一样,都是用来存储不重复元素的容器。set中的元素是不可变对象,这意味着 list 是不可以传入set中。
# Sets store ... well sets
empty_set = set()
# Initialize a set with a bunch of values. Yeah, it looks a bit like a dict. Sorry.
some_set = {1, 1, 2, 2, 3, 4} # some_set is now {1, 2, 3, 4}
调用add() 方法添加元素
set支持交叉并补
Do set intersection with &
# 计算交集
other_set = {3, 4, 5, 6}
filled_set & other_set # => {3, 4, 5}
# Do set union with |
# 计算并集
filled_set | other_set # => {1, 2, 3, 4, 5, 6}
# Do set difference with -
# 计算差集
{1, 2, 3, 4} - {2, 3, 5} # => {1, 4}
# Do set symmetric difference with ^
# 去掉交集
{1, 2, 3, 4} ^ {2, 3, 5} # => {1, 4, 5}
超集和子集的判断
# Check if set on the left is a superset of set on the right
{1, 2} >= {1, 2, 3} # => False
# Check if set on the left is a subset of set on the right
{1, 2} <= {1, 2, 3} # => True
超集和子集的概念
set 同样支持 in 、copy()等操作
Python中不支持switch语句!!!
Python中的else if 是 elif,如:
a = 1
if a > 1:
print("a>1")
elif a == 0:
print("a==0")
else:
print("a<0")
for animal in ["dog", "cat", "mouse"]:
# You can use format() to interpolate formatted strings
print("{} is a mammal".format(animal))
for i in range(4):
print(i)
# prints:0 1 2 3
for i in range(4, 8):
print(i)
# prints:4 5 6 7
for i in range(4, 8, 2):
print(i)
# prints:4 6
使用enumerate函数,同时迭代list的下标和元素:
"""
To loop over a list, and retrieve both the index and the value of each item in the list
prints:
0 dog
1 cat
2 mouse
"""
animals = ["dog", "cat", "mouse"]
for i, value in enumerate(animals):
print(i, value)
while 和C++类似
x = 0
while x < 4:
print(x)
x += 1 # Shorthand for x = x + 1
可迭代对象的使用
filled_dict = {"one": 1, "two": 2, "three": 3}
our_iterable = filled_dict.keys()
print(our_iterable) # => dict_keys(['one', 'two', 'three']). This is an object that implements our Iterable interface.
# We can loop over it.
for i in our_iterable:
print(i) # Prints one, two, three
可迭代对象不能使用[]来访问元素,但可以使用next关键字来获取下一元素。使用iter() 方法可以将可迭代对象转换成迭代器,也可以使用**list()**将其转换成列表:
# However we cannot address elements by index.
our_iterable[1] # Raises a TypeError
# An iterable is an object that knows how to create an iterator.
our_iterator = iter(our_iterable)
# Our iterator is an object that can remember the state as we traverse through it.
# We get the next object with "next()".
next(our_iterator) # => "one"
# It maintains state as we iterate.
next(our_iterator) # => "two"
next(our_iterator) # => "three"
# After the iterator has returned all of its data, it raises a StopIteration exception
next(our_iterator) # Raises StopIteration
# We can also loop over it, in fact, "for" does this implicitly!
our_iterator = iter(our_iterable)
for i in our_iterator:
print(i) # Prints one, two, three
# You can grab all the elements of an iterable or iterator by calling list() on it.
list(our_iterable) # => Returns ["one", "two", "three"]
list(our_iterator) # => Returns [] because state is saved
使用def 定义函数
# Use "def" to create new functions
def add(x, y):
print("x is {} and y is {}".format(x, y))
return x + y # Return values with a return statement
# Calling functions with parameters
add(5, 6) # => prints out "x is 5 and y is 6" and returns 11
# Another way to call functions is with keyword arguments
add(y=6, x=5) # Keyword arguments can arrive in any order.
也可以在参数名之前加上*表示任意长度的参数,参数会被转化成list:
# You can define functions that take a variable number of
# positional arguments
def varargs(*args):
return args
varargs(1, 2, 3) # => (1, 2, 3)
如果在参数前加上**表示接受一个dict
# You can define functions that take a variable number of
# keyword arguments, as well
def keyword_args(**kwargs):
return kwargs
# Let's call it to see what happens
keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"}
# You can do both at once, if you like
def all_the_args(*args, **kwargs):
print(args)
print(kwargs)
"""
all_the_args(1, 2, a=3, b=4) prints:
(1, 2)
{"a": 3, "b": 4}
"""
python是支持返回多个值的:
# Returning multiple values (with tuple assignments)
def swap(x, y):
return y, x # Return multiple values as a tuple without the parenthesis.
# (Note: parenthesis have been excluded but can be included)
x = 1
y = 2
x, y = swap(x, y) # => x = 2, y = 1
# (x, y) = swap(x,y) # Again parenthesis have been excluded but can be included.
python也可以返回一个函数,它支持函数式编程
# Python has first class functions
def create_adder(x):
def adder(y):
return x + y
return adder
add_10 = create_adder(10)
add_10(3) # => 13
在函数中使用和全局变量同名的变量不会造成覆盖,若要使用全局变量,需加上global 关键字
# Function Scope
x = 5
def set_x(num):
# Local var x not the same as global variable x
x = num # => 43
print(x) # => 43
def set_global_x(num):
global x
print(x) # => 5
x = num # global var x is now set to 6
print(x) # => 6
set_x(43)
set_global_x(6)
一个完整的类:
class Human:
# 类属性,可以直接通过Human.species调用,而不需要通过实例
species = "H. sapiens"
# 最基础的构造函数
# 加了下划线的函数和变量表示不应该被用户使用,其中双下划线的函数或者是变量将不会被子类覆盖
# 前后都有双下划线的函数和属性是类当中的特殊属性
def __init__(self, name):
# Assign the argument to the instance's name attribute
self.name = name
# Initialize property
self._age = 0
# 类中的函数,所有实例可以调用,第一个参数必须是self
# self表示实例的引用
def say(self, msg):
print("{name}: {message}".format(name=self.name, message=msg))
# Another instance method
def sing(self):
return 'yo... yo... microphone check... one two... one two...'
@classmethod
# 加上了注解,表示是类函数
# 通过Human.get_species来调用,所有实例共享
def get_species(cls):
return cls.species
@staticmethod
# 静态函数,通过类名或者是实例都可以调用
def grunt():
return "*grunt*"
@property
# property注解,类似于get,set方法
# 效率很低,除非必要,不要使用
def age(self):
return self._age
# This allows the property to be set
@age.setter
def age(self, age):
self._age = age
# This allows the property to be deleted
@age.deleter
def age(self):
del self._age
类的使用
# 这个是main函数也是整个程序入口的惯用写法
if __name__ == '__main__':
# 实例化一个类,获取类的对象
i = Human(name="Ian")
# 执行say方法
i.say("hi") # "Ian: hi"
j = Human("Joel")
j.say("hello") # "Joel: hello"
# i和j都是Human的实例,都称作是Human类的对象
# 类属性被所有实例共享,一旦修改全部生效
i.say(i.get_species()) # "Ian: H. sapiens"
Human.species = "H. neanderthalensis"
i.say(i.get_species()) # => "Ian: H. neanderthalensis"
j.say(j.get_species()) # => "Joel: H. neanderthalensis"
# 通过类名调用静态方法
print(Human.grunt()) # => "*grunt*"
# 不能通过对象调用静态方法,因为对象会传入self实例,会导致不匹配
print(i.grunt()) # => TypeError: grunt() takes 0 positional arguments but 1 was given
# 实例级别的属性是独立的,各个对象各自拥有,修改不会影响其他对象内的值
i.age = 42
# Get the property
i.say(i.age) # => "Ian: 42"
j.say(j.age) # => "Joel: 0"
# Delete the property
del i.age
# i.age # => this would raise an AttributeError
一般将不同的类放在不同的文件当中,import引入再实现继承
from human import Human
# Specify the parent class(es) as parameters to the class definition
class Superhero(Human):
# If the child class should inherit all of the parent's definitions without
# any modifications, you can just use the "pass" keyword (and nothing else)
# but in this case it is commented out to allow for a unique child class:
# pass
# 如果要完全继承父类的所有的实现,我们可以使用关键字pass,表示跳过。这样不会修改父类当中的实现
# Child classes can override their parents' attributes
species = 'Superhuman'
# 子类会完全继承父类的构造方法,也可以进行改造,比如额外增加一些参数
def __init__(self, name, movie=False,
superpowers=["super strength", "bulletproofing"]):
# 额外新增的参数
self.fictional = True
self.movie = movie
# be aware of mutable default values, since defaults are shared
self.superpowers = superpowers
# The "super" function lets you access the parent class's methods
# that are overridden by the child, in this case, the __init__ method.
# This calls the parent class constructor:
# 子类可以通过super关键字调用父类的方法
super().__init__(name)
# override the sing method
# 重写父类的sing方法
def sing(self):
return 'Dun, dun, DUN!'
# add an additional instance method
# 新增方法,只属于子类
def boast(self):
for power in self.superpowers:
print("I wield the power of {pow}!".format(pow=power))
if __name__ == '__main__':
sup = Superhero(name="Tick")
# Instance type checks
# 检查继承关系
if isinstance(sup, Human):
print('I am human')
# 检查类型
if type(sup) is Superhero:
print('I am a superhero')
# Get the Method Resolution search Order used by both getattr() and super()
# This attribute is dynamic and can be updated
# 查看方法查询的顺序
# 先是自身,然后沿着继承顺序往上,最后到object
print(Superhero.__mro__) # => (,
# => , )
# 相同的属性子类覆盖了父类
# Calls parent method but uses its own class attribute
print(sup.get_species()) # => Superhuman
# Calls overridden method
# 相同的方法也覆盖了父类
print(sup.sing()) # => Dun, dun, DUN!
# Calls method from Human
# 继承了父类的方法
sup.say('Spoon') # => Tick: Spoon
# Call method that exists only in Superhero
# 子类特有的方法
sup.boast() # => I wield the power of super strength!
# => I wield the power of bulletproofing!
# Inherited class attribute
sup.age = 31
print(sup.age) # => 31
# Attribute that only exists within Superhero
print('Am I Oscar eligible? ' + str(sup.movie))
python是支持多继承的,比如可以创建一个叫Batman的类,同时继承Superhero 和 Bat:
# And yet another class definition that inherits from Superhero and Bat
# superhero.py
from superhero import Superhero
from bat import Bat
# Define Batman as a child that inherits from both Superhero and Bat
class Batman(Superhero, Bat):
def __init__(self, *args, **kwargs):
# Typically to inherit attributes you have to call super:
# super(Batman, self).__init__(*args, **kwargs)
# However we are dealing with multiple inheritance here, and super()
# only works with the next base class in the MRO list.
# So instead we explicitly call __init__ for all ancestors.
# The use of *args and **kwargs allows for a clean way to pass arguments,
# with each parent "peeling a layer of the onion".
# 通过类名调用两个父类各自的构造方法
Superhero.__init__(self, 'anonymous', movie=True,
superpowers=['Wealthy'], *args, **kwargs)
Bat.__init__(self, *args, can_fly=False, **kwargs)
# override the value for the name attribute
self.name = 'Sad Affleck'
# 重写父类的sing方法
def sing(self):
return 'nan nan nan nan nan batman!'
执行这个类:
if __name__ == '__main__':
sup = Batman()
# Get the Method Resolution search Order used by both getattr() and super().
# This attribute is dynamic and can be updated
# 可以看到方法查询的顺序是先沿着superhero这条线到human,然后才是bat
print(Batman.__mro__) # => (,
# => ,
# => ,
# => , )
# Calls parent method but uses its own class attribute
# 只有superhero有get_species方法
print(sup.get_species()) # => Superhuman
# Calls overridden method
print(sup.sing()) # => nan nan nan nan nan batman!
# Calls method from Human, because inheritance order matters
sup.say('I agree') # => Sad Affleck: I agree
# Call method that exists only in 2nd ancestor
# 调用蝙蝠类的声呐方法
print(sup.sonar()) # => ))) ... (((
# Inherited class attribute
sup.age = 100
print(sup.age) # => 100
# Inherited attribute from 2nd ancestor whose default value was overridden.
print('Can I fly? ' + str(sup.fly)) # => Can I fly? False
使用yield 关键字创建生成器,每次调用的时候执行到yield 关键字处则停止,下次再调用还是从此处开始往下执行
# Generators help you make lazy code.
def double_numbers(iterable):
for i in iterable:
yield i + i
# Generators are memory-efficient because they only load the data needed to
# process the next value in the iterable. This allows them to perform
# operations on otherwise prohibitively large value ranges.
# NOTE: `range` replaces `xrange` in Python 3.
for i in double_numbers(range(1, 900000000)): # `range` is a generator.
print(i)
if i >= 30:
break
还可以使用() 来生成生成器
# Just as you can create a list comprehension, you can create generator
# comprehensions as well.
values = (-x for x in [1,2,3,4,5])
for x in values:
print(x) # prints -1 -2 -3 -4 -5 to console/terminal
# You can also cast a generator comprehension directly to a list.
values = (-x for x in [1,2,3,4,5])
gen_to_list = list(values)
print(gen_to_list) # => [-1, -2, -3, -4, -5]
引入functools当中的wraps之后,可以创建一个装饰器。装饰器可以在不修改函数内部代码的前提下,在外面包装一层其他的逻辑:
# Decorators
# In this example `beg` wraps `say`. If say_please is True then it
# will change the returned message.
from functools import wraps
def beg(target_function):
@wraps(target_function)
# 如果please为True,额外输出一句Please! I am poor :(
def wrapper(*args, **kwargs):
msg, say_please = target_function(*args, **kwargs)
if say_please:
return "{} {}".format(msg, "Please! I am poor :(")
return msg
return wrapper
@beg
def say(say_please=False):
msg = "Can you buy me a beer?"
return msg, say_please
print(say()) # Can you buy me a beer?
print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :(