#分配变量小技巧
x = 1
y = 2
#上下三组赋值效果一致
x, y = 1, 2
x = y = 1
不同于C语言,在python里,某一个变量的种类(class)不是固定的。
age: int = 20
# int 就是 Annotation,用于标注变量类型
# 如果linter 是 mypy,改变同一变量的类型,mypy就会报错
x = 1
print(id(x))
# 140705238406816
x = x + 1
print(id(x))
# 140705238406848
From above results, we can definitely get the conclusion that integer variables are immutable. Moreover, whenever the value of an integer variable is changed, Python will allocate a new memory address for the variable, with the same name, and the former memory will be released as nothing refers to it.
List is changeable.
Index is simply explained in the official tutorial book, and the demonstration is fantastic.
course = 'Python Programming'
print(len(course))
# this function can be used to calculate the length of a string
# or the item number of a set
print(course[0])
print(course[-2])
print(course[0:3])
print(course[:3])
print(course[0:])
print(course[:])
# these above functions are slice function
print(id(course))
print(id(course[0]))
whenever a string is sliced, Python will automatically create a copy of the string with a different type and memory address.
The above two results/addresses are different.
String is immutable variable but list is mutable.
print(r'D:\BaiduNetdisk\Download')
# in this case, \ will display as wish
first_name = 'John'
last_name = 'Smith'
full_name = f'Hello, {first_name} {last_name}'
full_name = 'Hello, {} {}'.format(first_name, last_name)
# the result of line 3 is identical to that of line 4
# personally, I prefer the first one; It's much more easy to type
# line 4 has similiar syntax to C#
# in C#, the code is like this:
# console.WriteLine("Hello,{0} {1}", first_name, last_name)
full_name = f'Hello, {len(first_name)} {4+5}'
# You can put any value in curly braces
# it works as if there is no quote.
You can put any value in curly braces, and it works as if there is no quote.
You can check all the methods within VScode. Follow the steps below
course = 'Python Programming'
course.
course.strip()
# 去前后空格
Python 支持二进制和十六进制,数字的写法和转化methods如下
x = 0b10
print(bin(x))
y = 0x12c
print(hex(y))
于此同时,Python可以做复数和高数运算
x = 10//3
# 除法求整数
x = 10 % 3
# 余数
x = 10**3
# 指数运算
x = 10**(-3)
# 开方运算
In Python, unlike languages like JS or C#, there is no constant, so, by convention, we use uppercase letters to tell other developers that the uppercased variable should be considered as a constant and not be modified.
Google “python 3 built-in functions” to get more information.
For the functions of modules, for example, the math module, you can google “python 3 math module.”
x = 1
print(int(x))
print(float(x))
print(bool(x))
# Falsy Vaule in Python(like JS)
# "" is empty string
# 0
# [] is empty list
# None (null in C languages)
In Python, unlike C languages, we use indentation (缩进) to specify code block( like {} in C#).
Python is a language very sensitive to line and indentation.
if condition:
pass
# pass works like placeholder
elif condition:
pass
else:
pass
In Python, there are three logical operators: and, or, and not
name = ""
if not name:
print("name is empty")
# This is hard to understand at the first glance
# Basically, NOT operator returns a Boolean value
# If the Boolean Value is FASLE
# the condition is met
name = " "
# a space within quote
if not name.strip():
print("name is empty")
# use strip method to remove space to get False value
# Otherwise, it won't work
age = 22
if age > 18 and age < 60:
if 18 < age < 60:
# line 17 and line 18 has the same function in Python.
类似C#里的问号冒号表达式,Python也有三元表达方式
age = 20
message = "Eligible" if age > 18 else "Not Eligible"
print(message)
A for loop is used for iterating over a sequence (that is either a list, a tuple, a dictionary, a set, or a string).
This is less like the for keyword in other programming languages, and works more like an iterator method as found in other object-orientated programming languages.
With the for loop we can execute a set of statements, once for each item in a list, tuple, set etc.
fruits = ["apple", "banana", "cherry"]
for x in fruits:
print(x)
for x in range(0, 10, 2):
print(x)
# range (起始数,最终数,step)
# 起始数和最终数都是inclusive,step默认是1
# range function is not a list, but a special class called range.
# range class is iterable in Python, and is similiar to list, string etc.
a = "xiaozhan is a good girl"
for x in a:
print(x, end="")
# or
print(a.split())
# in for loop, you don't need to define the x as a vriable
# x will be defined automatically and only works in the loop
Else 的理解和C#一样,不必多说
While Loop 和 For Loop的不同之处
For loop 会依次的把所有的item执行完,如果检索到需要的item,需要用到break命令来退出
while如果要实现上述功能,则不需要,因为它的结束条件是可以自定义的
for loop的优势就在于处理列表的时候,会非常的方便。
def increment(number: int, by: int = 1) -> tuple:
return (number, number + by)
# 可以在函数里,定义输入参数的类型,以及默认值
# 可以在函数里,定义输出的类型
print(increment(3))
def multiply(*list):
total = 1
for numbers in list:
total *= numbers
return total
print(multiply(2, 3, 4, 5))
# 这种函数能实现任意数字的相乘,不会限制数字的数量
# 原理是用*unpack吗,爱了爱了
忙了一天,抽烟太多,头痛,看不下去,鸽了
def save_user(**user):
print(user)
save_user(id=1, name='admin')
# **符号似乎是在使用function的时候定义variable的keyword
# Mosh说和JS的object很像,暂时不是很理解,需要后续补充
# 后续补充
# ** 用来unpack一个dictionary
原理查看[Unpacking Operator](#22- Unpacking Operator)
In Python, we have two types of variables: Local in function scope and Global in file scope.
In Python, unlike languages C# or JS, there is no block-level scope , which means we can definitely use a inside-if-clause variable outside the clause.
Specifically, in C# we always use variable i to start a loop, but the variable can’t be use outside this loop
for (int i = 0, i < 5, i ++)
{
console.WriteLine(i)
}
int a = i + 1;
Console.WriteLine(a)
// after this loop is finished, the value of i would be 5.
// but outside the loop, we can't use i because it is defined
// inside of the loop, but in Python, we can
Try this code in Python
for i in range(0, 6):
print(i)
a = i + 1
print(a)
Be ware, don’t change the value of a global variable in a function, otherwise you will get some side-effect.
Below is a bad practice, don’t do it except you have to.
message = 'a'
def greet():
global message
# used to tell Python that you want to change
# the global variable inside a function
message = 'b'
greet()
print(message)
F9 下断点
F10 下一步
F11 进入函数
几个实用的快捷键:
Home,End:当前行光标控制
ctrl+Home,ctrl+End:全文光标控制
Alt+上下箭头:移动当前选中行
Shift+Alt+上下箭头:选中自动向下当前选中行复制
FUNCTION+左右
FUNCTION+上下
ALT or OPTION +上下
Fizz Buzz 问题
给你一个整数n. 从 1 到 n 按照下面的规则打印每个数:
fizz
.buzz
.3
和5
整除,打印fizz buzz
.def fizz_buzz(number):
if number % 15 == 0:
return "fizz buzz"
if number % 3 == 0:
return "fizz"
if number % 5 == 0:
return "buzz"
return number
print(fizz_buzz(99))
27- Solution
letters = ['a', 'b', 'c']
matrix = [[0, 1], [2, 3]]
zeros = [0] * 5
combined = zeros + letters
numbers = list(range(20))
chars = list('Hello World')
print(chars)
numbers = list(range(20))
print(numbers[::-2])
# coooooooool
numbers = [1, 2, 3, 4, 4, 4, 4, 4, 4, 9]
first, *other, last = numbers
def multiply(*number):
pass
multiply(1, 2, 3, 4, 5, 6)
对比体会*的作用以及unpack list的操作
letters = ["a", "b", "c"]
for index, letter in enumerate(letters):
print(index, letter)
letters = ['a', 'b', 'c']
#add
letters.append('d')
letters.insert(1,"-")
# Remove
letters.pop(1)
letters.remove('b')
del letters[0:3]
letters.clear()
letters = ['a', 'b', 'c']
letters.index('d')
# return ERROR
letters = ['a', 'b', 'c']
if 'd' in letters:
print(letters.index('d'))
List有两种sort的办法。
numbers = [1, 4, 3, 2]
print(sorted(numbers))
# 上面的函数是重新生成一个物理地址,不会改变原本的list
# 所以上面的函数可以用于tuple
# 下面的相反,改变原有list,所以不能用于tuple
numbers.sort()
print(numbers)
items = [
('Products1', 10),
('Products2', 9),
('Products3', 13)
]
def sort_item(item):
return item[1]
items.sort(key=sort_item)
print(items)
# 上下两种方法是一个原理,对于KEY关键字的理解需要查证
def myfunc(e):
return len(e)
cars = ['Ford', 'Mitsubishi', 'BMW', 'VW']
cars.sort(reverse=True, key=myfunc)
print(cars)
items = [
('Products1', 10),
('Products2', 9),
('Products3', 13)
]
items.sort(key=lambda item:item[1])
print(items)
# 结果和上一节一样,只是用了lambada function以后会更简洁
lambda
如果我们想要把一个以tuple组合而成list里提取某个元素,比如上一节中的items里,我们只要价格,然后用价格组成一个list,应该怎么做?两种办法
items = [
('Products1', 10),
('Products2', 9),
('Products3', 13)
]
prices = []
for item in items:
prices.append(item[1])
print(prices)
第二种结合lambda的更简洁的办法
items = [
('Products1', 10),
('Products2', 9),
('Products3', 13)
]
prices = list(map(lambda item: item[1], items))
print(prices)
# 这个code 看起来比较复杂
# 因为map函数最后的结果是一个字符串形式的地图(map object)
# 所以需要list进行类似解压的操作,还原后原理如下
def extract_prices(item):
return item[1]
x = map(extract_prices, items)
for prices in x:
print(prices)
实现以下功能
items = [
('Products1', 10),
('Products2', 9),
('Products3', 13)
]
filtered = []
for item in items:
if item[1] >= 10:
filtered.append(item)
print(filtered)
更加elegant的办法(改变了原有的list)
items = [
('Products1', 10),
('Products2', 9),
('Products3', 13)
]
for item in items:
if item[1] < 10:
items.remove(item)
print(items)
Mosh教的更加更加好的方法
items = [
('Products1', 10),
('Products2', 9),
('Products3', 13)
]
filtered = list(filter(lambda item: item[1] >= 10, items))
print(filtered)
Python 独有的List Comprehension功能,可以方便的实现上两节的输出结果。更加更加更加elegant。
prices = list(map(lambda item: item[1], items))
prices = [item[1] for item in items]
filtered = list(filter(lambda item: item[1] >= 10, items))
filtered = [item for item in items if item[1] >= 10]
#这里的方括号只是因为我们要创建一个list,comprehension不局限于list
values = [ expression for item in items]
作用图示
list1 = [1, 2, 3]
list2 = [10, 20, 30]
# 目标结果 [(1,10), (2, 20), (3, 30)]
print(list(zip(list1, list2)))
LIFO, Last in first out, 没啥好说的
可以说stack比栈从字面上好理解多了
FIFO,first in first out.在这种模式下,我们需要考虑的就是,如果我们有一个长达百万的list,我们一旦删除index==0的item,那么这个list剩下的所有items的index都会发生变动,这样对于内存的占用是十分巨大不可接受的。
所以,在这种情况下,可以使用deque module(双向队列),deque module似乎是在内存中做了两种标记,从头到尾和从尾到头两个方向,怀疑中间数是两个方向的终点。所以这样的话,我们无论删除list中的哪个item,都不会导致内存负荷过大。具体应用如下
from collections import deque
queue = deque([])
Tuple is basically a read-only list, and we can’t modify anything of it. However, you can use + and * to create a new tuple.
x, y = y, x
# 在python里,这个数值的交换不是通过中间的第三个变量
# 而是通过对于tuple的赋值完成的。
# 也就是说,实际的运作机制如下
x, y = (y, x)
Arrays are similar with List, and the only difference is that arrays is performed a little bit faster in computer.
from array import array
numbers = array("i", [1, 2, 3])
# in the above code, the character "i" is a mark of typecode
# it is used to states the type of items in array
A set is a collection which is unordered and unindexed, and the items in set are unduplicated. In Python sets are written with curly brackets.
numbers = [1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2]
uniques = set(numbers)
print(uniques)
# output
# {1, 2}
consequence = {1, 3, 4, 5}
print(uniques | consequence) # 并集
print(uniques & consequence) # 交集
print(uniques - consequence) # 减去set 2 中有的元素
print(uniques ^ consequence) # 返回不共有
# output
# {1, 2, 3, 4, 5}
# {1}
# {2}
# {2, 3, 4, 5}
Dictionary in Python is an unordered collection of data values, used to store data values like a map, which unlike other Data Types that hold only single value as an element, Dictionary holds key:value
pair. Key value is provided in the dictionary to make it more optimized.
point = {'x': 1, 'y': 2}
point = dict(x=1, y=2)
# 定义dictionary的两种方式
# 几种dictionary和for loop的应用
for key in point:
print(key, point[key])
for x in point.items():
print(x)
for key, value in point.items():
print(key, value)
# output
# x 1
# y 2
# ('x', 1)
# ('y', 2)
# x 1
# y 2
values = {}
for x in range(5):
values[x]= x * 5
# 两种方式,一种结果
values = {x: x * 2 for x in range(5)}
print(values)
Generator functions allow you to declare a function that behaves like an iterator, i.e. it can be used in a for loop. Unlike list, which saves every item in the memory, generator create a new value in each iteration.
values = (x * 2 for x in range(5))
print(type(values))
# output
#
* can be used to unpack any iterable.
** can be used to unpack a dictionary.
numbers = [1, 2, 3]
print(*numbers)
print(1, 2, 3)
print(*range(5))
print(*'hello')
first = {'x': 1}
second = {'x': 10, 'y': 2}
combined = {**first, **second, 'z': 1}
print(combined)
# output
# {'x': 10, 'y': 2, 'z': 1}
sentence = "This is a common interview question"
char_frequency = {char: sentence.count(char) for char in sentence}
result = sorted(
char_frequency.items(),
key=lambda kw: kw[1],
reverse=True)
print(result[0])
A Quick Note
程序的容错性:如果一个程序因为用户有意或者无意的错误输入而导致报错终结,这个程序的抗性就非常的弱。
try:
age = int(input("Age:"))
except ValueError:
print("You didn't enter a valid age.")
else:
print("No exceptions were thrown.")
print("Execution countines")
we can use try
and except
to make our programs more resistant to crash.
try:
age = int(input("Age:"))
xfactor = 10/age
except (ValueError, ZeroDivisionError):
print("You didn't enter a valid age.")
except:
print("Zero can't be divided")
else:
print("No exceptions were thrown.")
print("Execution countines")
# like the rule in FOR loop, whenever an exception is executed
# the others will be automatically ignored.
finally
is a clause to indicate the end stage of a program.
onefile = open("smaple.txt")
with open("smaple.txt") as onefile, open("another_sample.txt") as another_file:
print("file opend")
# in the second case, you don't need `finally` clause any more.
What is Context Management Protocol? what are magic methods _enter_
and _exit_
?
I am not sure about the point of this chapter. It seemingly shows the usage of with
clause, but I think there is something deeper than I can understand.
补充:if an object supports Context Management Protocol, or in other words, it has __enter__
and __exit__
methods, it can be used with with as
statement.
for more details, check these pages:
https://docs.python.org/3/reference/datamodel.html#context-managers
https://docs.python.org/3/reference/compound_stmts.html#with
As Mosh said in the video class, raise
exception is costly, and there is a better way to perform. The only reason to demonstrate raise
statement is that we might see it in other people’s codes.
def calculate_xfactor(age):
if age <= 0:
raise ValueError("Age cannot be 0 or less.")
return 10 / age
try:
calculate_xfactor(-1)
except ValueError as error:
print(error)
# output
# Age cannot be 0 or less.
if you can handle the problem with if
clause, be ware to use raise
exception in your code. The second one will cost about 4 times time to perform.
Class is a blueprint for creating new objects, or vice verse, objects are instances of class.
name convention: for variables, we use all lower letters and separate words with underscore. However, for class, every word should be started with upper case, and no underscore be used to separate words.
Parameter and argument have same meaning in Computer English.
class Point:
def draw(self):
print("draw")
point = Point()
print(type(point))
print(isinstance(point, Point))
Constructor is specially method would be called whenever an object is created.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def draw(self):
print(f"Point ({self.x},{self.y})")
point = Point(1, 2)
point.draw()
熟练了就OK,细节太多反而不必去记
Class level attributes are shared with all objects in the class, meanwhile the attributes can be changed outside the class. When the changes happen, all attributes of objects belong this class will be automatically changed.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def draw(self):
print(f"Point ({self.x},{self.y})")
Point.default_color = "red"
point = Point(1, 2)
point.draw()
print(point.default_color)
In the above case, all the two methods are instance methods, which are used to modify an object in the class. While some time we need to define a subtype object with the default attributes, we could use class method. In the below codes, zero()
is a typical class method—whenever you define an variable with this method, it inherits the attributes within.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
@classmethod
def zero(cls):
return cls(0, 0)
def draw(self):
print(f"Point ({self.x}, {self.y})")
point = Point.zero()
point.draw()
Magic methods are called automatically by Python interpreter depending on how we use the objects and classes.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"({self.x}, {self.y})"
@classmethod
def zero(cls):
return cls(0, 0)
def draw(self):
print(f"Point ({self.x}, {self.y})")
point = Point.zero()
print(point)
还是不能理解magic method的作用机制
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
point = Point(1, 2)
other = Point(1, 2)
print(point == other)
# output
# False
# In this case, the addresses of the two points were compared.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __eq__(self, value):
return self.x == value.x and self.y == value.y
point = Point(1, 2)
other = Point(1, 2)
print(point == other)
# output
# True
# return 后面的句子是判断条件,它的结果就是magic method的结果
# 同理,判断大小也适用此格式
# 再次同理,如果判断条件一致,有gt就不需要再写lt了
以加法为例
注意运算的return值为Point
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"({self.x}, {self.y})"
def __add__(self, other):
return Point(self.x + other.x, self.y + other.y)
point = Point(1, 2)
other = Point(1, 2)
print(point+other)
class TagCloud:
def __init__(self):
self.tags = {}
def add(self, tag):
self.tags[tag.lower()] = self.tags.get(tag.lower(), 0) + 1
def __getitem__(self, tag):
return self.tags.get(tag.lower(), 0)
def __setitem__(self, tag, count):
self.tags[tag.lower()] = count
def __len__(self):
return len(self.tags)
def __iter__(self):
return iter(self.tags)
cloud = TagCloud()
cloud.add("Python")
cloud["python"]
cloud["python"] = 10
len(cloud)
for tag in cloud:
print(tag)
# 一一对照
class TagCloud:
def __init__(self):
self.__tags = {}
def add(self, tag):
self.tags[tag.lower()] = self.__tags.get(tag.lower(), 0) + 1
def __getitem__(self, tag):
return self.__tags.get(tag.lower(), 0)
def __setitem__(self, tag, count):
self.tags[tag.lower()] = count
def __len__(self):
return len(self.__tags)
def __iter__(self):
return iter(self.__tags)
cloud = TagCloud()
cloud.add("Python")
len(cloud)
cloud["python"]
cloud["python"] = 10
for tag in cloud:
print(tag)
不同于C#,Python里没有真正意义上的private members,double underscores("__")更多是用来提示用户:此变量为私人变量。但是实际上,它还是可以在外界被访问。
A property is an object that set in front of an attribute and allows us to get or set the value of the attribute.
unpythonic way to code
class Product:
def __init__(self, price):
self.set_price(price)
def get_price(self):
return self.price
def set_price(self, value):
if value < 0:
raise ValueError("price cannot be negative")
self.price = value
product1 = Product(-11)
print(product1.price)
pythonic way
class Product:
def __init__(self, price):
self.price = price
@property
def price(self):
return self.__price
@price.setter
def price(self, value):
if value < 0:
raise ValueError("price cannot be negative")
self.__price = value
product1 = Product(-11)
print(product1.price)
简单到不想做笔记,鸽了
The most basic class
in python is object
method overriding: when a constructor of a subclass is called, the constructor of the parent class is overridden.
class Animal:
def __init__(self):
self.age = 1
class Mammal(Animal):
def __init__(self):
super().__init__() # 可以引用任何method
self.weight = 2
m = Mammal()
print(m.age)
print(m.weight)
class Flyer:
def fly(self):
pass
class Swimmer:
def swim(self):
pass
class FlyingFish(Flyer, Swimmer):
pass
class InvalidOperationError(Exception):
pass
# 自定义错误类型
class Stream:
def __init__(self):
super().__init__()
self.opened = False
def open(self):
if self.opened:
raise InvalidOperationError("The file is already opened.")
self.opened = True
def close(self):
if not self.opened:
raise InvalidOperationError("The file is already closed.")
self.opened = False
class StreamFile(Stream):
def read(self):
print("reading data from file")
class NetworkFile(Stream):
def read(self):
print("reading data from network")
from abc import ABC, abstractmethod
class InvalidOperationError(Exception):
pass
class Stream(ABC):
def __init__(self):
self.opened = False
def open(self):
if self.opened:
raise InvalidOperationError("The file is already opened.")
self.opened = True
def close(self):
if not self.opened:
raise InvalidOperationError("The file is already closed.")
self.opened = False
@abstractmethod
def read(self):
pass
class StreamFile(Stream):
def read(self):
print("reading data from file")
class NetworkFile(Stream):
def read(self):
print("reading data from network")
stream = StreamFile()
print(stream.opened)
stream.open()
print(stream.opened)
stream.open()
非常神奇的设计思路,如果存在一大堆的东西需要批量审查处理,这个思路是最合适的。
Poly = many
morph = form
from abc import ABC, abstractmethod
class UIControl(ABC):
@abstractmethod
def draw(self):
pass
class TextBox(UIControl):
def draw(self):
print("TextBox")
class DropDownList(UIControl):
def draw(self):
print("DropDownList")
def draw(controls):
for control in controls:
control.draw()
ddl = DropDownList()
other = TextBox()
draw([ddl, other])
If you behave like a duck, python will recognize you as a duck.
class TextBox():
def draw(self):
print("TextBox")
class DropDownList():
def draw(self):
print("DropDownList")
def draw(controls):
for control in controls:
control.draw()
ddl = DropDownList()
other = TextBox()
draw([ddl, other])
class TrackableList(list):
def append(self, object):
print("append called")
return super().append(object)
textlist = TrackableList()
textlist.append("1")
所有extended的内容必须要在return
命令之前
If you are dealing with a class within which only data exists, you might need namedtuple
rather than create a class. However, be aware of that tuple
is immutable.
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p1 = Point(x=1, y=2)
print(p1.__doc__)
p2 = Point(x=1, y=2)
print(p1 == p2)
print(id(p1))
print(id(p2))
# tuple is immutalbe, so if you want to change the attribute within the tuple
# just create a new tuple like this
p1 = Point(x=10, y=20)