基础代码

项目结构

parent/
    __init__.py
    one/
        __init__.py
    two/
        __init__.py
    three/
        __init__.py

HelloWorld

hello.js

console.log('hello Node.js')
$ node hello.js

注释

"""模块注释"""
from typing import (
    Union, Optional, Any, IO, Iterable, AnyStr, Dict, List, Tuple
)


# 单行注释
def add(a: int, b: int):
    """加法

    实现加法的逻辑

    :param a: 数值1
    :param b: 数值2

    :return:

    Example
    --------
    >>> add(1, 2)
    """
    return a + b


class Client:
    """Client的简介描述

    更多关于Client的信息描述。
    此处为段落描述内容 ...

    :param object data: 可迭代对象或者IO对象的类型
    :param str param1:
        字符串参数说明
    :param (:obj:`str`, optional) param2:
        可选参数说明,类型可能是字符或者字典
    :param param3:
        可选参数说明, 任意类型
        段落说明...
    :argument int:
        不定参数说明
    :keyword str keyword1:
        关键字1说明
    :keyword float keyword2:
        关键字2说明
    :keyword bool keyword3: 关键字3说明

    See also
    --------
    参见内容在这里写

    Notes
    -----
    注解内容在这里写

    """

    info = [{'id': 1}], [{'active': True}]

    def __init__(
            self,
            data: Union[Iterable[AnyStr], IO[AnyStr]],
            param1: str,
            param2: Optional[Union[str, Dict[str, Any]]] = None,
            param3: Optional[Any] = None,
            *args: int,
            **kwargs: Any
            ):
        self.data = data
        self.param1 = param1
        self.param2 = param2
        self.param3 = param3
        self.args = args
        self.kwargs = kwargs

    @classmethod
    def get_client_info(cls) -> Tuple[List[Dict[str, int]], List[Dict[str, bool]]]:
        """函数功能介绍

        :returns:
            二元组返回值说明
        :rtype:
            tuple(list(dict(str, str), list(dict(str, str))

        Examples
        --------
        >>> Client.get_client_info()
        ([{'id': 1}], [{'active': True}])
        """
        return cls.info

备注

开源代码参考

声明变量

age = 8


# 私有变量
# ====================================
# 使用场景: A类和B类都定义一个run方法,C类同时继承A类和B类,B类使用run方法时可能调用了A类的run方法,这时可以使用私有变量 避免命名冲突问题

class A:
    def __run(self):
        pass


class B:
    def __run(self):
        pass

    def call_run(self):
        self.__run()


class C(A, B):
    def __init__(self):
        pass

常量

PI = 3.14
print(PI)

字符串

age = 18
print(f"我今年{age}岁了")

name = "黑马程序员"
message = "学IT就来 %s" % name
print(message)

class_num = 57
avg_salary = 16781
message = "Python大数据学科, 北京%s期, 毕业平均工资: %s" % (class_num, avg_salary)
print(message)

"""
其他格式符号

* %s - 将内容转换成字符串,放入占位位置
* %d - 将内容转换成整数,放入占位位置
* %f - 将内容转换成浮点型,放入占位位置
"""

列表

# arr = [10, 20, 30]
arr = ['刘德华', '张学友', '黎明', '郭富城', 'pink老师']
print(arr)
print(arr[0])
print(len(arr))

# 循环
for item in arr:
    print(item)

元组

"""
演示tuple元组的定义和操作
"""

# 定义元组
t1 = (1, "Hello", True)
t2 = ()
t3 = tuple()
print(f"t1的类型是: {type(t1)}, 内容是: {t1}")
print(f"t1的类型是: {type(t2)}, 内容是: {t2}")
print(f"t1的类型是: {type(t3)}, 内容是: {t3}")

# 定义单个元素的元素
t4 = ("hello", )
print(f"t1的类型是: {type(t4)}, 内容是: {t4}")
# 元组的嵌套
t5 = ((1, 2, 3), (4, 5, 6))
print(f"t1的类型是: {type(t5)}, 内容是: {t5}")
# 下表索引去取出内容
num = t5[1][2]
print(f"从嵌套元组中取的数据是: {num}")

# 元组的操作: index查找方法
t6 = ("传智教育", "黑马程序员", "Python")
index = t6.index("黑马程序员")
print(f"在元组t6中查找黑马程序员,的下标是: {index}")

# 元组的操作: count统计方法
t7 = ("传智教育", "黑马程序员", "黑马程序员", "黑马程序员", "Python")
num = t7.count("黑马程序员")
print(f"在元组t7中统计黑马程序员的数量有: {num}个")
# 元组的操作: len函数统计元组元素数量
t8 = ("传智教育", "黑马程序员", "黑马程序员", "黑马程序员", "Python")
num = len(t8)
print(f"t8元组中的元素有: {num}")

# 元组的遍历: while
index = 0
while index < len(t8):
    print(f"元组的元素有: {t8[index]}")
    index += 1

# 元组的遍历: for
for element in t8:
    print(f"元组的元素有: {element}")

# 修改元组内容
t9 = (1, 2, ["itheima", "itcast"])
print(f"t9的内容是: {t9}")
t9[2][0] = "黑马程序员"
t9[2][1] = "传智教育"
print(f"t9的内容是: {t9}")

字典

"""
演示数据容器字典的定义
"""

# 定义字典
my_dict = {"王力鸿": 99, "周杰轮": 88, "林俊节": 77}

# 从字典中基于Key获取Value
score = my_dict["王力鸿"]
print(f"王力鸿的考试分数是: {score}")

"""
演示字典的常用操作
"""
my_dict = {"周杰轮": 99, "林俊节": 88, "张学油": 77}
# 新增元素
my_dict["张信哲"] = 66
print(my_dict)
# 更新元素
my_dict["周杰轮"] = 33
# 删除元素
score = my_dict.pop("周杰轮")
print(score)
# 清空元素
my_dict.clear()
# 获取全部的Key
my_dict = {"周杰轮": 99, "林俊节": 88, "张学油": 77}
keys = my_dict.keys()
print(keys)
# 遍历字典
for key in keys:
  print(my_dict[key])
# 统计字典内的元素数量
num = len(my_dict)
print(num)

类型系统

s = "pink"
print(type(s))

# ***************类型转换*****************

s = '123'
print(int(123))

反射

package main

import (
	"fmt"
	"reflect"
)

// Kind https://pkg.go.dev/reflect#Kind
func Kind() {

	for _, v := range []any{"hi", 42, func() {}} {
		switch v := reflect.ValueOf(v); v.Kind() {
		case reflect.String: // 判断是字符串类型
			fmt.Println(v.String())
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			fmt.Println(v.Int())
		default:
			fmt.Printf("unhandled kind %s", v.Kind())
		}
	}
}

func main() {
	fmt.Println("Kind")
	fmt.Println("==============================")
	Kind()
}

参见

应用案例:

  • Json.Marshal, 入参v是any, reflect.ValueOf(v), 然后用到reflect的各种api去判断和处理

警告

慎用reflect包

  • 虽然提供了强大的功能,但是它可能会带来一定的性能开销。因此,在可能的情况下,考虑使用类型断言或者泛型代替

  • 过度依赖reflect可能会使得代码难以理解和维护

类型声明文件

typescript中的一种特殊文件,通常以.d.ts作为拓展名。它的主要作用是为现有的JavaScript代码提供类型信息

export function add(a, b){
    return a + b;
}

export function mul(a, b){
    return a * b
}

条件判断

def if_else_case(a: int):
    if a == 0:
        print("执行 if 语句块")
    elif a == 1:
        print("执行 else if 语句块")
    else:
        print("执行 else 语句块")

循环

for i in range(10):
    if i == 5:
        continue
    print("位置1 执行 for 语句块 i:", i)

i = 0
b = True
while b:
    print("位置2 执行 for 语句块 i:", i)
    i += 1
    if i >= 10:
        b = False

# 列表循环
LIST = [1, 2, 3, 4, 5, 6, 7, 8, 9]
for index, data in enumerate(LIST):
    print("位置3 执行 for 语句块 index: {}, data: {}".format(index, data))

# 字典循环
mp = {"A": "a", "B": "b", "C": "c"}
for key, value in mp.items():
    print("位置4 执行 for 语句块 key: {}, value: {}".format(index, value))

# 字符串循环
STR = "今天天气很好"
for index, char in enumerate(STR):
    print("位置5 执行 for 语句块 key: {}, char: {}".format(index, char))

# 死循环
j = 0
while True:
    print("位置6 执行死循环 j:", j)
    j += 1
    if j >= 10:
        break

switch

# match表面上像C、Java或JavaScript中的switch语句,但其实它更像Rust或Haskell中的模式匹配。

def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"
        case _:
            return "Something's wrong with the internet"

异常

import sys

# 处理多个异常
# ==============================
try:
    raise RuntimeError
except (RuntimeError, TypeError, NameError):
    pass


class HY000(Exception):
    pass


def create_synonym_db(db_name):
    ...
    db_err_msg = 'Unknown database ' + db_name
    # 抛出自定义异常
    raise HY000(db_err_msg)

else子句

try … except 语句有一个可选的 else 子句,在使用时必须放在所有的 except 子句后面。对于在try 子句不引发异常 时必须执行的代码来说很有用。例如:

for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except OSError:
        print('cannot open', arg)
    else:
        print(arg, 'has', len(f.readlines()), 'lines')
        f.close()

finally

>>> try:
...     raise KeyboardInterrupt
... finally:
...     print('Goodbye, world!')
...
Goodbye, world!
KeyboardInterrupt
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>

如果存在 finally 子句,则 finally 子句将作为 try 语句结束前的最后一项任务被执行。 finally 子句不论 try 语句是否产生了异常都会被执行。

异常链

raise 语句允许可选的 from 子句,它启用了链式异常。 例如:

# exc must be exception instance or None.
raise RuntimeError from exc

小技巧

用途: 转换异常

禁用异常链可使用 from None 习语

打印异常内容

import traceback

try:
    print(1/0)
except Exception:
    # 输出到控制台
    traceback.print_exc()
    # 保存到变量
    err = traceback.format_exc()

导包

# 正常导包
import string
# 别名
import string as s

print(string.Template)
print(s.Template)

# 使用from导入time的sleep功能
from time import sleep
print("你好")
sleep(5)
print("我好")

# 使用*导入time模块的全部功能
from time import *
print("你好")
sleep(5)
print("我好")

# 如果一个模块文件中有`__all__`变量, 当使用`from xxx import *`导入时,只能导入这个列表中的元素

# 通过绝对路径导入模块
# ==============================================
import sys
from importlib import import_module

sys.path.insert(0, 'module所在目录的绝对路径')
if 'module' in sys.modules:
    # 删除缓存, 避免导入同名的其他模块
    del sys.modules['module']
module = import_module('.module', package='module所在目录名')

函数

str1 = "itheima"
str2 = "itcast"
str3 = "python"


def my_len(data):
    """需求: 统计字符串的长度,不使用内置函数len()"""
    count = 0
    for i in data:
        count += 1
    print(f"字符串{data}的长度是{count}")


my_len(str1)
my_len(str2)
my_len(str3)


def user_info(name, age, gender):
    print(f"姓名是: {name}, 年龄是: {age}, 性别是: {gender}")


# 位置参数
user_info('小明', 20, '男')
# 关键字参数
user_info(name='小王', age=11, gender='女')


# 缺省参数(默认值)
def user_info(name, age, gender='男'):
    print(f"姓名是: {name}, 年龄是: {age}, 性别是: {gender}")


user_info('小天', 13)


# 不定长 - 位置不定长, *号, 会作为元组存在,接收不定长数量的参数
def user_info(*args):
    print(f'args参数的类型是: {type(args)}, 内容是: {args}')


user_info(1, 2, 3, '小明', '男孩')


# 关键字不定长, **号
def user_info(**kwargs):
    print(f'kwargs参数的类型是: {type(kwargs)}, 内容是: {kwargs}')


user_info(name='小王', age=11, gender='男孩', addr='北京')


# 演示函数作为参数传递
def _test_func(compute):
    result = compute(1, 2)
    print(f"compute参数的类型是: {type(compute)}")
    print(f"计算结果是: {result}")


def compute(x, y):
    return x + y


_test_func(compute)
# 演示lambda匿名函数
_test_func(lambda x, y: x + y)


默认参数

原生不支持默认值, 实现方式可参考testcontainers的开源代码: https://github.com/testcontainers/testcontainers-go/blob/v0.33.0/modules/mysql/mysql.go

使用的例子, 传入可选项参数修改默认值:

package main

import (
    "context"
    "log"
    "path/filepath"
    "github.com/testcontainers/testcontainers-go"
    "github.com/testcontainers/testcontainers-go/modules/mysql"
)

func main() {
    ctx := context.Background()

    mysqlContainer, err := mysql.Run(ctx,
        "mysql:8.0.36",
        mysql.WithConfigFile(filepath.Join("testdata", "my_8.cnf")),
        mysql.WithDatabase("foo"),
        mysql.WithUsername("root"),
        mysql.WithPassword("password"),
        mysql.WithScripts(filepath.Join("testdata", "schema.sql")),
    )
    defer func() {
        if err := testcontainers.TerminateContainer(mysqlContainer); err != nil {
            log.Printf("failed to terminate container: %s", err)
        }
    }()
    if err != nil {
        log.Printf("failed to start container: %s", err)
        return
    }
}

以下是mini实现支持默认值参数:

package main

import (
	"fmt"
	"log"
	"strings"
)

// 默认值
const (
	rootUser            = "root"
	defaultUser         = "test"
	defaultPassword     = "test"
	defaultDatabaseName = "test"
)

// defaultImage {
const defaultImage = "mysql:8.0.36"

// MySQLContainer represents the MySQL container type used in the module
type MySQLContainer struct {
	//Container
	username string
	password string
	database string
}

func WithDefaultCredentials() CustomizeRequestOption {
	return func(req *GenericContainerRequest) error {
		username := req.Env["MYSQL_USER"]
		password := req.Env["MYSQL_PASSWORD"]
		if strings.EqualFold(rootUser, username) {
			delete(req.Env, "MYSQL_USER")
		}
		if len(password) != 0 && password != "" {
			req.Env["MYSQL_ROOT_PASSWORD"] = password
		} else if strings.EqualFold(rootUser, username) {
			req.Env["MYSQL_ALLOW_EMPTY_PASSWORD"] = "yes"
			delete(req.Env, "MYSQL_PASSWORD")
		}

		return nil
	}
}

// ContainerRequest represents the parameters used to get a running container
type ContainerRequest struct {
	HostAccessPorts []int
	Image           string
	Entrypoint      []string
	Env             map[string]string
	ExposedPorts    []string // allow specifying protocol info
	Cmd             []string
	Labels          map[string]string
	Tmpfs           map[string]string
	RegistryCred    string // Deprecated: Testcontainers will detect registry credentials automatically
	Name            string // for specifying container name
	Hostname        string
	WorkingDir      string              // specify the working directory of the container
	ExtraHosts      []string            // Deprecated: Use HostConfigModifier instead
	Privileged      bool                // For starting privileged container
	Networks        []string            // for specifying network names
	NetworkAliases  map[string][]string // for specifying network aliases
	User            string              // for specifying uid:gid
	SkipReaper      bool                // Deprecated: The reaper is globally controlled by the .testcontainers.properties file or the TESTCONTAINERS_RYUK_DISABLED environment variable
	ReaperImage     string              // Deprecated: use WithImageName ContainerOption instead. Alternative reaper image
	AutoRemove      bool                // Deprecated: Use HostConfigModifier instead. If set to true, the container will be removed from the host when stopped
	AlwaysPullImage bool                // Always pull image
	ImagePlatform   string              // ImagePlatform describes the platform which the image runs on.
	Binds           []string            // Deprecated: Use HostConfigModifier instead
	ShmSize         int64               // Amount of memory shared with the host (in bytes)
	CapAdd          []string            // Deprecated: Use HostConfigModifier instead. Add Linux capabilities
	CapDrop         []string            // Deprecated: Use HostConfigModifier instead. Drop Linux capabilities
}

// GenericContainerRequest represents parameters to a generic container
type GenericContainerRequest struct {
	ContainerRequest      // embedded request for provider
	Started          bool // whether to auto-start the container
	Reuse            bool // reuse an existing container if it exists or create a new one. a container name mustn't be empty
}

// ContainerCustomizer is an interface that can be used to configure the Testcontainers container
// request. The passed request will be merged with the default one.
type ContainerCustomizer interface {
	Customize(req *GenericContainerRequest) error
}

// CustomizeRequestOption is a type that can be used to configure the Testcontainers container request.
// The passed request will be merged with the default one.
type CustomizeRequestOption func(req *GenericContainerRequest) error

func (opt CustomizeRequestOption) Customize(req *GenericContainerRequest) error {
	return opt(req)
}

// RunContainer creates an instance of the MySQL container type
func RunContainer(opts ...ContainerCustomizer) (*MySQLContainer, error) {
	// 在实例化定义默认值
	// =====================================================
	req := ContainerRequest{
		Image:        defaultImage,
		ExposedPorts: []string{"3306/tcp", "33060/tcp"},
		Env: map[string]string{
			"MYSQL_USER":     defaultUser,
			"MYSQL_PASSWORD": defaultPassword,
			"MYSQL_DATABASE": defaultDatabaseName,
		},
	}

	genericContainerReq := GenericContainerRequest{
		ContainerRequest: req,
		Started:          true,
	}

	opts = append(opts, WithDefaultCredentials())

	// 覆盖默认值
	// =================================================
	for _, opt := range opts {
		if err := opt.Customize(&genericContainerReq); err != nil {
			return nil, err
		}
	}

	username, ok := req.Env["MYSQL_USER"]
	if !ok {
		username = rootUser
	}
	password := req.Env["MYSQL_PASSWORD"]

	if len(password) == 0 && password == "" && !strings.EqualFold(rootUser, username) {
		return nil, fmt.Errorf("empty password can be used only with the root user")
	}

	database := req.Env["MYSQL_DATABASE"]

	return &MySQLContainer{username, password, database}, nil
}

func TerminateContainer(c *MySQLContainer) error {
	return nil
}

// 处理选项数据
// =======================================

func WithDatabase(database string) CustomizeRequestOption {
	return func(req *GenericContainerRequest) error {
		req.Env["MYSQL_DATABASE"] = database
		return nil
	}
}

func WithUsername(username string) CustomizeRequestOption {
	return func(req *GenericContainerRequest) error {
		req.Env["MYSQL_USER"] = username
		return nil
	}
}

func WithPassword(password string) CustomizeRequestOption {
	return func(req *GenericContainerRequest) error {
		req.Env["MYSQL_PASSWORD"] = password
		return nil
	}
}

// main
// ======================================

func main() {
	mysqlContainer, err := RunContainer(
		WithDatabase("foo"),
		WithUsername("root"),
		WithPassword("password"),
	)
	defer func() {
		if err := TerminateContainer(mysqlContainer); err != nil {
			log.Printf("failed to terminate container: %s", err)
		}
	}()
	if err != nil {
		log.Printf("failed to start container: %s", err)
		return
	}
}

类/结构体

class Phone:
    IMEI = None  # 序列号
    producer = "ITCASE"  # 厂商

    def __str__(self):
        return f"Phone类对象, name:{self.name}, age: {self.age}"

    def __lt__(self, other):
        return self.age < other.age

    def __le__(self, other):
        return self.age <= other.age

    def __eq__(self, other):
        return self.age == other.age

    # 提供私有成员变量
    __is_5g_enable = False  # 5g状态

    # 提供私有成员方法
    def __check_5g(self):
        if self.__is_5g_enable:
            print("5g开启")
        else:
            print("5g关闭, 使用4g网络")

    def call_by_5g(self):
        """成员方法"""
        print("使用5g网络进行通话")


# 定义子类, 复写父类成员
class MyPhone(Phone):
    producer = "ITHEIMA"  # 复写父类的成员属性

    def call_by_5g(self):
        print("开启CPU单核模式, 确保通话的时候省电")
        # 方式1
        # print(f"父类的厂商是: {Phone.producer}")
        # Phone.call_by_5g(self)
        # 方式2
        print(f"父类的厂商是: {super().producer}")
        super().call_by_5g()
        print("关闭CPU单核模式, 确保性能")


phone = MyPhone()
phone.call_by_5g()
print(phone.producer)
# 在子类中, 调用父类成员

抽象类

abstract class Package {

constructor(public weight: number) {} // 抽象方法 abstract calculate(): number // 具体方法 printPackage(){

console.log(包裹重量为: ${this.weight})

}

}

class StandardPackage extends Package{
constructor(

weight: number, public unitPrice: number

) {

super(weight);

} calculate(): number {

return this.weight * this.unitPrice

}

}

const s1 = new StandardPackage(10, 5) console.log(s1.calculate());

捕获异常

# arr = [10, 20, 30]
arr = ['刘德华', '张学友', '黎明', '郭富城', 'pink老师']
print(arr)
print(arr[0])
print(len(arr))

# 循环
for item in arr:
    print(item)

打断点

<script>
    // https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/debugger
    function potentiallyBuggyCode() {
      const v = 1
        console.log(v)
      debugger;
      // do potentially buggy stuff to examine, step through, etc.
    }

    potentiallyBuggyCode()
</script>

接口

// 定义类结构
// ================================================
// PersonInterface接口
interface PersonInterface{
    name: string
    age: number
    speak(n: number): void
}

class Person implements PersonInterface{
    constructor(
        public name: string,
        public age: number,
    ) {}
    speak(n: number) {
        console.log(`你好, 我叫${this.name}, 我的年龄是${this.age}`)
    }
}

// 定义对象结构
// ==========================================
interface UserInterface{
    name: string
    readonly gender: string // 只读属性
    age?: number // 可选属性
    run: (n: number) => void
}

const user: UserInterface ={
    name: "张三",
    gender: "男",
    age: 18,
    run(n){
        console.log(`奔跑了${n}米`)
    }
}

// 定义函数结构
// =====================================

interface CountInterface{
    (a: number, b: number): number;
}

const count: CountInterface = (x, y) => {
    return x + y
}

// 接口之间的继承
// ===========================
interface StudentInterface extends PersonInterface{
    grade: string // 年级
}

const stu: StudentInterface = {
    name: '张三',
    age: 18,
    grade: '初二',
    speak(n: number) {}
}

泛型

// 泛型函数
// ==============================

function logData<T>(data: T): T{
    console.log(data)
    return data
}

logData(100)
logData('hello')

// 泛型接口
// =============================
interface PersonInterface<T> {
    name: string,
    age: number,
    extraInfo: T
}

let p1: PersonInterface<string>
let p2: PersonInterface<number>

p1 = { name: '张三', age: 18, extraInfo: '一个好人'}
p2 = { name: '张三', age: 18, extraInfo: 250}

// 泛型类
// ===============================
class Person<T> {
    constructor(
        public name: string,
        public age: number,
        public extraInfo: T
    ) {}
    speak(){
        console.log(`我叫${this.name}今年${this.age}岁了`)
        console.log(this.extraInfo)
    }
}

const p3 = new Person<number>("tom", 30, 250);