calc
__all__ = ("name",) # 通过all的方式决定暴露哪一些变量或者说函数 但是只能够影响from * 的这种用法
name = "wozen"
def add1(x: int, y: int) -> int:
return x + y
def add1(x: float, y: float) -> float:
print("float加法")
return x + y
from calc.add import add1, name
# from calc.add import *
def sub(x: int, y: int) -> int:
print(add1(x, y))
return x - y
# 每多一个文件就多了一个package
print(sub(1, 2))
class_test
# 封装问题
# 栈
class Stack:
def __init__(self):
self.items = []
def isEmpty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def size(self):
return len(self.items)
# 既然有了列表为什么我们还要基于list去实现一个栈呢?
# - 随机获取数据 l[0] - 很有可能误操作 都达不到我们想要的栈的效果
# 上边的类 封装了变量 - list以及基于这些变量的方法 go如果想要达到这个封装效果 那么就一定要解决1.变量的封装 2.方法的封装
# 另外一个场景 我们现在有一组课程的信息需要保存 一门课程有 课程名 课程的url 课程的价格
class Courese:
def __init__(self, name, price, url):
self.name = name
self.price = price
# self._url = url # 大家都认可的一种编码规范 这种权限级别的控制 java是可以做到的
self.__url = url # 大家都认可的一种编码规范 这种权限级别的控制 java是可以做到的
courses = []
course1 = Courese("django", 100, "https://www.imooc.com")
# print(course1._url) # 保护成员的访问类 _url
# print(course1.__url)
courses.append(course1)
course2 = Courese("scrapy", 100, "https://www.imooc.com")
courses.append(course2)
# 如果我们仅仅只关心数据的话,还有另一种数据结构更合适,tuple更省内存 性能更高
course2 = []
new_course1 = ("django", 100, "https://www.imooc.com")
course2.append(new_course1)
from collections import namedtuple
# namedtuple很像是一个只能封装数据的类 但是namedtuple的性能比class高 内存比class小很多
NewCourse = namedtuple('Course', 'name price url')
a = NewCourse(name="django", price=100, url="https://www.imooc.com")
print(a.price)
course2.append(a)
# go语言的struct更像是namedtuple 尽量配置简单的语法尽量猜测你的意图
name = "" # 对空字符串 判断是false情况
name = None
name = 0
name = []
if name:
print("yes")
s = Stack()
# python中一切皆对象
print(Stack.isEmpty(s))
# s.isEmpty() => Stack.isEmpty(s)
class Course:
def __init__(self, name, price, url):
self.name = name
self.price = price
self.url = url
def set_price(self, price):
self.price = price
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def speak(self):
print("姓名:{}, 年龄:{}".format(self.name, self.age))
class Student(Person):
def __init__(self, name, age, school):
super().__init__(name, age)
self.school = school
def detail(self):
print("姓名:{}, 年龄:{},学校:{}".format(self.name, self.age, self.school))
# 方法和函数 差异并不大
c = Course("django", 100, "https://www.imooc.com")
c.set_price(200)
print(c.price)
s = Student("anwma", 22, "慕课网")
s.speak()
s.detail()
duck_type
# go语言的接口(protol 协议)设计是参考了鸭子类型(python)和java的接口
# 什么是鸭子类型?什么叫协议
# 当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子
# 采用的是面向对象的类继承
class Animal:
def born(self):
pass
def walk(self):
pass
class Dog(Animal):
def born(self):
pass
def walk(self):
pass
class Cat(Animal):
pass
dog = Dog()
# dog是不是动物类 实际上dog就是动物类 忽略了鸭子类型 对于用惯面向对象的人来说 这个做法有点古怪
# python语言本身的设计上来说是基于鸭子类型实现的
# dog是本身animal,并不是由继承关系确定的,而是由你的这个类是不是实现了这些方法
# Animal实际上只是定义了一些方法的名称而已 其他任何类 你继不继承只要实现了这个Animal()里面的方法那你这个类就是Animal类型
from typing import Iterable # 实际上list没有继承 Iterable这个类 好比是一份协议
a = []
print(type(a))
print(isinstance(a, Iterable)) # 这是因为 list里面实现了list方法 魔法方法 只是实现了它的方法
b = tuple()
print(isinstance(b, Iterable))
class Company(object):
def __init__(self, employee_list):
self.employee = employee_list
# 实现以下魔法方法可用for 迭代 不实现会抛异常
def __iter__(self):
return iter(self.employee)
# company = Company(["tom", "bob", "jane"])
company = Company([100, 110, 120])
for em in company:
print(em)
# for语句可以对dict list tuple set等类型进行for循环
# for语句可以对iterable类型进行操作,只要你实现了__iter__那你就可以进行for循环
# 你的类继承了什么不重要 你的类名称不重要 重要的是你实现了什么魔法方法
# if isinstance(company, Iterable):
# print("company是Iterable类型")
# else:
# print("company不是Iterable类型")
price = [100, 200, 300] # python本身是基于鸭子类型设计的一门语言 - 协议最重要
# price = (100, 200, 300)
# print(sum(price))
print(sum(company))
# 强调 什么是鸭子类型 非常推荐大家去好好学习python中的魔法方法
# django + xadmin
# scrapy
sort_test
class Course:
def __init__(self, name, price, url):
self.name = name
self.price = price
self.url = url
def __str__(self):
return "{}-{}".format(self.name, self.price)
l = []
c1 = Course("django", 200, "")
c2 = Course("scrapy", 100, "")
c3 = Course("tornado", 300, "")
c4 = Course("sanic", 100, "")
l.append(c1)
l.append(c2)
l.append(c3)
l.append(c4)
# data = [1, 3, 5, 2, 6, 8, 9]
# data.sort()
l.sort(key=lambda x: x.price)
for item in l:
print(item)
# print(data)
print(l)
other
# 错误和异常
# 除法函数
def div(a, b):
# 稍微认真一点的程序员都会在除法中判断我们的被除数 b 是否为0
if b == 0:
# raise Exception("被除数不能为0") # 异常
return None, "被除数不能为0"
# dict访问了一个不存在的key, 在list中对空的list进行了data[0]
user_info_dict = {
"name": "wozen",
"age": 18
}
if "weight" in user_info_dict:
user_info_dict["weight"]
# 如果每个地方都这样写,代码中的if就太多了,那就是你的bug问题,这种问题就一定要早发现
return a / b, None
# 如果你的这个函数 - div返回的是None 这个时候调用者不会出问题
# 错误和异常 错误就是可以预先知道的出错情况 这个时候我们把这个情况叫做错误
# 不可预知的问题叫做异常 程序员写的代码不严谨造成了某个地方产生了异常
def cal():
while 1:
a = int(input())
b = int(input())
v, err = div(a, b)
if err is not None:
print(err)
else:
print(v)
# try:
# div(a, b)
# except Exception as e:
# print(e)
# 后面还有逻辑
# 被调用函数传递的异常会导致我们的cal函数出现异常
# cal()
import re
desc = "wozen:22"
m = re.match("wozen:(.*)", desc)
if m is not None:
print(m.group(1))
from typing import get_type_hints, Iterable, MutableMapping
from functools import wraps
from inspect import getfullargspec
# 函数参数和返回值的类型声明
# import socket
#
# s = socket.socket()
# s.send()
def add2(a: int, b: float = 3.5) -> float:
return a + b
def validate_input(obj, **kwargs):
hints = get_type_hints(obj)
for para_name, para_type in hints.items():
if para_name == "return":
continue
if not isinstance(kwargs[para_name], para_type):
raise TypeError("参数:{} 类型错误,应该是:{}".format(para_name, para_type))
def type_check(decorator):
@wraps(decorator)
def wrapped_decorator(*args, **kwargs):
func_args = getfullargspec(decorator)[0]
kwargs.update(dict(zip(func_args, args)))
validate_input(decorator, **kwargs)
return decorator(**kwargs)
return wrapped_decorator
@type_check
def add(a: int, b: int) -> int:
return a + b
# 调用的时候才能发现类型问题
if __name__ == "__main__":
# print(add(1, 2))
# print(add2(1))
# 有些人还并不满意
# print(add("bobby:", "18"))
#
# print(get_type_hints(add))
# print(add.__annotations__)
# print(bin(13))
# name = "wozen:楚心云"
# print(name[2])
# print(len("wozen:楚心云"))
# in可以用在很多地方
# if "wozen" in name:
# print("yes")
#
# name.index("w")
# name.count("b")
# name.startswith("b")
# name.endswith("云")
# print("hello".upper())
# print("HELLO".lower())
# print("hello world".split())
# print(",".join(["hello", "world"]))
# name = "wozen"
# age = 18
# print("name: %s,age: %d" % (name, age))
# print("name:{},age:{}".format(name, age))
# print(f"name:{name},age:{age}")
# name = input("请输入你的姓名: ")
# print(name)
#
# age = int(input("请输入你的年龄: "))
# print(type(age))
# sum = 0
# python中对于for的用法很统一
# for i in range(1, 11):
# sum += i
# print(sum(range(1, 11)))
# print(sum)
# for item in "bobby":
# print(item)
for index, item in enumerate("bobby"):
print(index, item)
name = "hello:我的世界"
print(name[6])
# 一个简单的计算器
# a = int(input("请输入第一个数:"))
# op = input("操作符:")
# b = int(input("请输入第二个数:"))
#
#
# def add(a, b):
# return a + b
#
#
# def sub(a, b):
# return a - b
#
#
# def div(a, b):
# return a / b
#
#
# def mul(a, b):
# return a * b
#
#
# op_dict = {
# "+": add,
# "-": sub,
# "/": div,
# "*": mul,
# }
# func = op_dict[op]
# print(func(a, b)(a, b))
# 把函数当作普通的变量使用 还可以当作一个返回值 这个特性就是一等公民的特性
# if op == "+":
# print(a + b)
# elif op == "-"
# print(a - b)
# elif op == "*"
# print(a * b)
# elif op == "/"
# print(a / b)
import threading
# 有一些情况是需要两种操作都出现 1.打开/关闭 文件 2.数据库的连接 (开启 关闭) 3.锁(获取锁 释放锁)
def read_file(file_name):
f = open(file_name) # 打开文件成功之后执行逻辑
with open(file_name, "w") as f:
sum = 0
data = [1, 2]
for line in f:
sum += int(line)
# sum += line # 这一行代码可能有异常 很容易出现异常
# f.close()
print("before return ")
# re_data = data # 将结果暂存到临时的变量当中去
re_data = sum # sum是int 是值传递 将3拷贝到re_data中去 = 3
lock = threading.Lock()
lock.acquire()
try:
# 此处是多行处理逻辑 这些就可能抛出异常
pass
except Exception as e:
pass
finally:
lock.release()
# 此处跳往 finally 执行
return re_data
# except Exception as e:
# # f.close()
# pass
# finally:
# print("close file")
# data.append(3)
# f.close()
# lock.release # 此处可能抛出异常
# 1.代码出现异常 导致 close 执行不到
# 2.我们忘记close了 无论是否正常运行代码都能够执行到指定逻辑
print(read_file("xxx.txt"))
# 代码很丑陋, 但是一旦逻辑复杂 这种代码大量的充斥了我们的代码中
# 但是 finally有一些细节我们需要知道 就有了一个印象 finally会在return 之后运行
# 事实上真的是这样吗?
# 原因: 实际上finally是在return 之前调用
# finally中是可以return 而且这个地方有了return 就会覆盖原本的return
#
from typing import List
from copy import deepcopy
def print_list(course: List[str]):
course[0] = "bobby"
print(course)
# 引用传递
course = ["django", "scrapy", "tornado", "python", "golang"]
# 深拷贝 浅拷贝
# print_list(deepcopy(course))
# print(type(course))
sub_course = course[1:4] # 左闭右开的区间[1:4] 新的list 底层的数据是复制出来的
my_list = list
sub_course[0] = "imooc"
print(sub_course)
print(type(sub_course))
print(course) # src_arr 不被影响到
# print(type(sub_course))
# print(course)
# if "scrapy" in course: # 内部无非就是实现了一个魔法方法 __contains__
# print("yes")
a = [1, 2, 3]
b = a[:]
b[0] = 8
print(a)
print(b)
m = {
"a": "va",
"b": "vb"
}
a = None
b = None
print_list(id(a), id(b))
print(m.get("d", "wozen"))
if "a" in m:
print("yes")
# from collections import namedtuple
# def main():
# print("hello", end="")
# print(" python", end="")
#
#
# if __name__ == '__main__':
# # main()
# # 定义匿名变量
# my_list = ["bobby", "imooc", "test"]
# for _, item in enumerate(my_list):
# print(item)
# # 元组 (无法被修改)
# sex_tuple = ("male", "female")
from calc.add import add1 as add1_int
from calc.add_float import add1
print(add1(1, 2))
print(add1_int(1, 2))
# python中没有package说明自己属于什么package 和包名 和文件名称是挂钩的
# 1. 采用dict映射
def print_A():
print("A")
def print_B():
print("B")
def print_C():
print("C")
def print_D():
print("D")
score = 90
switch = {
90: print_A,
80: print_B,
70: print_C,
60: print_D,
}
switch[score]()
# 1.python的类型相比go而言少很多 int float
# 2.字符串转int
data = "123"
int_data = int(data, 16)
print(type(int_data), int_data)
# 3.int转字符串
data_str = str(int_data)
print(type(data_str), data_str)
# 4.float类型转换
data_float = float("3.1415")
print(type(data_float), data_float)
float_str = str(data_float)
print(type(float_str), float_str)
# 5.bool类型转换 字符串转换bool 只要字符串不是空字符串 都是true
# bool_data = bool("true1")
# bool_data2 = bool("")
# print(bool_data)
# print(bool_data2)
from distutils.util import strtobool
bool_data = strtobool("1")
print(bool_data)
import sys
a = 20
def myfunc():
# python中没有定义变量的说法
global a
# 修改全局变量
a = 10
print(a)
def myfunc2():
sex = "Male"
print("Female")
# 运行中才会发现很多问题,有很多问题会在你的程序已经部署到生产环境中运行到某些逻辑之下才会出现
out_str = ""
if sex == "Male":
out_str = "性别:男"
print(out_str)
if __name__ == "__main__":
# myfunc() # 局部
# print(a) # 全局
# myfunc2()
# print(bin(2))
# print(oct(2))
# print(hex(2))
# print(ord("a"))
# print(ord("吴"))
age = 18
# 对于python来说,int占用字节是动态的,python的int我们不用担心超过上限
print(sys.getsizeof(age))
print(sys.getsizeof(71.2))
# print("a" + 1) # "a"表示字符 单引号不代表字符
# python3.8 提供了一个新的运算符 - 海象运算符 可以为我们的表达式赋值
# course_list = ["django", "scrapy", "tornado"]
# if course_size := len(course_list) >= 3:
# print("课程较多,课程数量:{}".format(course_size))
# Output: true
# if (course_size := len(course_list)) >= 3:
# print("课程较多,课程数量:{}".format(course_size))
# Output: 3
# len(course_list)只调用了一次
# len(course_list)调用了两边
# version 1
# powers = [len(course_list), len(course_list) ** 2, len(course_list) ** 3]
# version 2
# course_size = len(course_list)
# powers = [course_size, course_size ** 2, course_size ** 3]
# version 3 海象运算符
# powers = [course_size := len(course_list), course_size ** 2, course_size ** 3]
# print(powers)
# import re
# desc = "bobby:18"
# if m := re.match("bobby:(.*)", desc):
# age = m.group(1)
# print(age)
# age = 18
# age := 18 error
# age += 5
# 类型注解
# 动态语言不需要声明变量类型 这种做法在很多人眼里是不好维护的代名词
# len(course_list) 调用了两边 len(course_list)只调用了一次
# 变量类型说明 一般情况下我们会通过变量名来隐含的说明该变量的类型
age: int = 18 # 说明该类型是int类型
# python有大量的内置类型 int float bool str bytes
name: str = "bobby"
sex: bool = True
weight: float = 75
x: bytes = b"test"
age = "18"
# 类型的声明 不会实际影响使用 , hints 提示作用 pycharm是支持这种提示的
print(age)
# 但是实际上这样做也会有明显的缺点,损失了python本身的灵活性
# 复杂数据类型的声明
# courses: list = ["django", "scrapy", "tornado"] # 有问题
from typing import List, Set, Dict, Tuple
courses: List[str] = ["django", "scrapy", "tornado"]
courses.append("asyncio")
courses.append(1)
print(courses)
user_info: Dict[str, float] = {"bobby": 75.2}
names: Tuple[int, ...] = (1, 2, 3)
name: str
name = "bobby"
# 函数变量类型的声明其实意义更大