第四章、数据类型

Python数据类型-LMLPHP

     在 Python 中,数据类型可以分为两大类:基本数据类型(Primitive Data Types)和引用数据类型(Reference Data Types)。 

一、基本数据类型(不可变)

        基本数据类型是 Python 中的简单数据类型,它们是不可变的,即一旦创建后,其值不可修改。当进行某些操作时,会创建新的对象,而不是修改原有对象。Python 中的基本数据类型包括:

  • 整数(int):表示整数值,例如 42
  • 浮点数(float):表示浮点数值,例如 3.14
  • 布尔值(bool):表示布尔类型,值为 TrueFalse
  • 字符串(str):表示字符串类型,例如 'hello'
  • 元组(tuple):使用圆括号 () 表示,一旦创建后,其内容不可修改。

1、不可变原理

        基本数据类型是不可变的,主要是为了提高性能、安全性和一致性,以及满足 Python 设计哲学中的 "不可变性" 特性。

        性能: 不可变对象在创建后其值不可更改,因此在使用时不需要为其分配额外的内存来处理可能的修改。这使得在操作这些类型的数据时更加高效,特别是对于字符串和整数等常用的数据类型。

        安全性: 不可变性确保对象的值不会被意外更改。这在多线程环境下是非常重要的,因为多个线程可以同时访问和操作相同的数据。如果数据是可变的,可能会导致竞态条件(Race Condition)和不一致的结果。不可变性可以避免这类问题的发生,简化了线程之间的数据共享和同步。

        一致性: 不可变性使得对象的值在其生命周期内保持不变,这在函数调用、数据传递和编程中的其他情况下非常有用。函数接收不可变对象作为参数时,可以确保函数内部不会改变传递进来的参数值,这有助于代码的可预测性和可维护性。

        Python 设计哲学: Python 设计哲学之一是 "Simple is better than complex"(简单胜于复杂),不可变性使得 Python 语言在某些方面变得更简单、更容易理解。同时,Python 支持 "duck typing"(鸭子类型),允许开发者自由选择使用可变或不可变数据类型,从而根据实际需求灵活地处理数据。

        综上所述,不可变性在 Python 中是一个重要的概念,它为代码的性能、安全性和一致性提供了许多好处,并符合 Python 设计的理念。

2、案例

整数(int)

x = 42
print(x)  # 输出 42

# 修改整数的值
x = 99
print(x)  # 输出 99

        在上面的示例中,我们首先创建了一个整数对象 x 并将其赋值为 42,然后将 x 的值修改为 99。这是因为整数是不可变的,我们实际上是创建了一个新的整数对象 99,而不是修改原来的对象。

字符串(str)

name = "Alice"
print(name)  # 输出 "Alice"

# 修改字符串的值
name = "Bob"
print(name)  # 输出 "Bob"

        在上面的示例中,我们首先创建了一个字符串对象 name 并将其赋值为 "Alice",然后将 name 的值修改为 "Bob"。同样,字符串是不可变的,我们实际上是创建了一个新的字符串对象 "Bob",而不是修改原来的对象。

元组(tuple)

t = (1, 2, 3)
print(t)  # 输出 (1, 2, 3)

# 修改元组的值(不可行)
# t[0] = 10  # TypeError: 'tuple' object does not support item assignment

        在上面的示例中,我们创建了一个元组对象 t,并将其赋值为 (1, 2, 3)。由于元组是不可变的,我们无法通过索引修改元组中的元素,尝试这样做会引发 TypeError

        这些示例说明了整数、字符串和元组等数据类型的不可变性。当我们试图修改这些数据类型的值时,实际上是创建了新的对象,而不是在原有对象上进行修改。

二、引用数据类型(可变)

        引用数据类型是用来存储对象的引用(内存地址),而不是直接存储对象本身的数据值。引用数据类型在赋值时实际上是复制对象的引用,而不是复制对象本身。以下是 Python 中的引用数据类型:

        引用数据类型是 Python 中用于存储复杂数据的数据类型,它们是可变的,即可以在创建后修改其内容。这些数据类型实际上是对象的引用,而不是直接存储数据本身。修改引用数据类型的内容时,实际上是在操作对象本身,而不是创建新的对象。Python 中的引用数据类型包括:

  1. 列表(list):使用方括号 [] 表示,可以通过索引修改其中的元素。
  2. 字典(dict):使用花括号 {} 表示,可以通过键修改其中的值。
  3. 集合(set):使用花括号 {} 表示,可以添加、删除元素。

1、可变原理

列表(list): 列表是由一系列有序元素组成的数据结构,使用方括号 [] 表示。列表的元素可以通过索引进行访问、添加、删除和修改。例如:

my_list = [1, 2, 3]
print(my_list)  # 输出 [1, 2, 3]

# 修改列表元素
my_list[0] = 10
print(my_list)  # 输出 [10, 2, 3]

# 添加元素
my_list.append(4)
print(my_list)  # 输出 [10, 2, 3, 4]

# 删除元素
my_list.remove(2)
print(my_list)  # 输出 [10, 3, 4]

由于列表的内容可以修改,它被称为可变数据类型。

集合(set): 集合是一个无序的、不重复的元素集合,使用花括号 {} 表示。集合可以添加和删除元素。例如:

my_set = {1, 2, 3}
print(my_set)  # 输出 {1, 2, 3}

# 添加元素
my_set.add(4)
print(my_set)  # 输出 {1, 2, 3, 4}

# 删除元素
my_set.remove(2)
print(my_set)  # 输出 {1, 3, 4}

由于集合的内容可以修改,它也被称为可变数据类型。

字典(dict): 字典是一种键-值对的数据结构,使用花括号 {} 表示。字典中的值可以通过键进行访问、添加、修改和删除。例如:

my_dict = {"name": "Alice", "age": 30}
print(my_dict)  # 输出 {"name": "Alice", "age": 30}

# 修改值
my_dict["age"] = 31
print(my_dict)  # 输出 {"name": "Alice", "age": 31}

# 添加键值对
my_dict["city"] = "New York"
print(my_dict)  # 输出 {"name": "Alice", "age": 31, "city": "New York"}

# 删除键值对
del my_dict["name"]
print(my_dict)  # 输出 {"age": 31, "city": "New York"}

由于字典的内容可以修改,它同样被称为可变数据类型。

可变数据类型在处理需要频繁插入、删除或修改元素的场景时非常有用,而不可变数据类型则更适用于那些需要保持数据不变性的场景。在编程中,根据需要选择合适的数据类型是非常重要的。

三、None类型

        在Python中,None 是一个特殊的数据类型,用于表示空值或缺失的值。它类似于其他编程语言中的 nullnilNone 表示一个不存在的对象或变量,并且是Python的空值对象。

None 在Python中通常用于以下情况:

1、None类型用法

1、初始化变量
x = None
2、返回空值
def do_something():
    # 执行一些操作,但不需要返回值
    return None

        在 Python 中,None 是一个特殊的常量,表示空值或空对象。它不是一个类型,而是一个对象。它通常用作函数没有明确返回值时的默认返回值,或者用作变量初始化时的默认值。在 Python 中,None 属于 NoneType 类型。

        当一个函数的返回值类型被注释为 None 时,它表示该函数不返回任何值,或者说返回一个空值。这通常在函数没有明确返回值的情况下使用,或者在函数执行某些操作但不需要返回特定值时使用。例如,如果一个函数只是用来执行某些操作,而不需要返回任何结果,您可以将其返回类型注释为 None

        在 Python 的类型注释中,函数的返回值注释应该是返回值的类型,而不是具体的返回值本身。None 作为特殊的常量表示空值,可以用作函数的返回值,同时它也是 NoneType 类型的唯一实例。因此,可以将函数的返回值类型注释为 None 表示函数没有返回任何有意义的值。

        例如,当函数不需要返回特定值时,可以使用 None 作为返回值。在类型注释中,您可以使用 None 表示函数的返回类型为 None,表示该函数不返回任何有意义的值。这种做法是为了提供对函数行为的清晰说明,而不是返回值本身。

下面是一个简单的示例,演示了函数的返回值注释为 None 的情况:

def log_message(message: str) -> None:
    print(f"Log: {message}")

result = log_message("This is a log message")
print(result)  # 输出为 None

在这个例子中,log_message 函数不返回任何有意义的值,它只是打印了日志消息。因此,函数的返回值被注释为 None,表示它不会返回任何实际的值。

3、默认参数值
def greet(name=None):
    if name is None:
        return "Hello, Guest!"
    else:
        return f"Hello, {name}!"

        在这个例子中,greet 函数接受一个名为 name 的参数,并将其默认值设置为 None。如果在调用函数时没有传递 name 参数,则使用默认值 None

2、None空值对象和NoneType类型的关系

NoneNoneType 是两个不同的概念,但它们之间有关联。

1、None
  • None 是 Python 中表示空值或缺失的特殊对象。它是一个关键字,表示一个不存在的对象或变量。在条件判断中,None 被视为假值。
  • None 并不是一个类,而是一个对象,它只是一个特殊的值,用于表示空值对象。
2、NoneType
  • NoneType 是 Python 中表示 None 值的类型。它是一个真正的数据类型,用于表示 None 对象的类型。
  • NoneNoneType 类型的唯一实例对象。也就是说,NoneNoneType 类的一个实例。

None 是 Python 中表示空值的特殊常量,它属于 NoneType 类型。在 Python 中,NoneType 是一个单例类型,表示只有一个实例的类型,即 None。当一个变量没有被赋予任何值时,它通常会被默认设置为 None

可以使用 type() 函数来检查变量的类型。例如:

x = None
print(type(x))  # 输出:<class 'NoneType'>
help("NoneType")
"""
No Python documentation found for 'NoneType'.
Use help() to get the interactive help utility.
Use help(str) for help on the str class.
"""

        由于 None 是一个特殊的类型,它不能被视为其他任何类型的子类型。它是一个独立的类型,表示空值或空对象。在 Python 中,它经常用于表示空的、未知的或不存在的值。 

        所以,可以说 NoneNoneType 类的实例对象。但是需要注意的是,None 并不是一个类本身,而是 NoneType 类的实例,用于表示空值。在 Python 中,NoneNoneType 并不是可以自由创建的对象或类型,而是内置到语言中的特殊值和类型。

三、Python中的所有数据类型都是对象(实例对象),所有类都是数据类型,所有数据类型都是类

四、判断数据类型运算符

1、type() 内置类

例如:

x = 42
y = "Hello"
z = [1, 2, 3]

print(type(x))  # 输出:<class 'int'>
print(type(y))  # 输出:<class 'str'>
print(type(z))  # 输出:<class 'list'>

2、isinstance() 内置函数

例如:

x = 42

if isinstance(x, int):
    print("x 是整数类型")
else:
    print("x 不是整数类型")

isinstance()函数侧重于类,不是类型,因此不需要类型提前引用

class A(object):
    def main(self) -> bool:
        a: A = A()
        return isinstance(a, A)

if __name__ == '__main__':
    print(A().main()) #True

3、type()isinstance() 的区别

  • type() 函数返回对象的精确类型,它会返回一个类的对象。
  • isinstance() 函数可以检查对象是否为指定类型或其子类,它会返回布尔值 True 或 False。

        在实际编程中,type()isinstance() 经常用于检查函数参数的数据类型或进行条件判断,以确保正确处理不同类型的数据。根据具体需求,您可以选择合适的方式来判断数据的类型。

第五章、运算符重载和特殊方法

一、概述

        运算符重载和特殊方法是Python面向对象编程中的重要概念,它们允许你自定义对象的行为,并使得你的类能够支持内置运算符和函数的操作。特殊方法是以双下划线开头和结尾的方法,它们在Python中有特殊的用途,用于实现运算符重载。

二、特殊方法

1、定义

2、以实例方法为主

3、作用理解

        这些方法在Python中有特殊的用途,当你在自定义类中定义了这些特殊方法时,Python会在适当的时候自动调用这些方法。这就是运算符重载的关键,你可以通过实现这些特殊方法来定制你的类对象在使用内置运算符时的行为。

__abs__这样的方法是Python中的特殊方法(也称为魔术方法或双下划线方法)。它们是在对象中定义的特殊方法,用于实现特定的操作或行为。这些特殊方法的命名都以双下划线开始和结束,如__abs____add____sub__等。

__abs__方法是用于返回对象的绝对值的特殊方法。对于整数和浮点数来说,绝对值是该数的非负值。对于复数来说,绝对值是复数的模(magnitude,即复数到原点的距离)。

调用__abs__方法的方式是使用内置函数abs(),Python会自动调用对象的__abs__方法来计算绝对值。

让我们看看如何调用__abs__方法:

  1. 整数的绝对值:
num = -10
print(abs(num))  # 输出:10,调用了num对象的__abs__方法,返回绝对值10。

复数的绝对值:

complex_num = 3 + 4j
print(abs(complex_num))  # 输出:5.0,调用了complex_num对象的__abs__方法,返回复数的模5.0。

特殊方法之所以奇怪是因为它们的命名使用了双下划线,这样的命名使它们在Python中具有特殊的含义,而且这些方法会在特定的情况下被自动调用,而不需要显式地调用。这使得Python的对象模型非常灵活和强大,可以通过定义这些特殊方法来自定义对象的行为。例如,在自定义类中,你可以实现__abs__方法来定义该类对象的绝对值计算方式。

是的,你理解得很对!当一个对象定义了__abs__方法,就表示该对象可以求绝对值。

在Python中,当你调用内置函数abs()时,它会自动寻找对象的__abs__方法,并调用该方法来计算对象的绝对值。因此,如果一个对象定义了__abs__方法,那么它就具备了计算绝对值的能力。

这种通过特殊方法实现的机制称为"运算符重载",它允许用户自定义对象在使用内置运算符(如+-*等)时的行为。对于绝对值的例子来说,如果你想自定义某个类的对象的绝对值计算方式,你只需要在该类中定义__abs__方法,然后Python会在调用abs()时自动调用该方法。

运算符重载和特殊方法是Python面向对象编程的重要概念,它使得你可以灵活地定义对象的行为和操作,增强了代码的灵活性和可读性。在使用特殊方法时,需要遵循Python的特殊方法命名约定,以确保这些方法能够在适当的时候被正确调用。

4、Python源码中特殊方法没有可见具体的实现代码

        特殊方法之所以没有具体的实现源码,是因为它们是 Python 语言的内置功能。这些方法是在 Python 解释器中实现的,而不是作为普通的 Python 代码存在的。当对象执行特定操作时,Python 解释器会根据对象所属的类去查找对应的特殊方法,并在内部调用它们。因此,在类定义中通常使用 pass 占位符来表示特殊方法没有实际实现。这样可以使类定义更加简洁,而特殊方法的具体实现是由 Python 解释器来完成的。

 5、自定义类中须重载实现特殊方法,才能达到效果

        当我们在自定义类时,如果希望对象在特定操作下有特殊的行为,可以通过实现这些特殊方法来自定义类的行为。这样,在对象执行相应操作时,Python 解释器会调用我们定义的特殊方法,从而实现我们自定义的行为。

6、Python解释器自动调用特殊方法说明

通过符号调用

通过方法调用

二、运算符重载(动作重载)

        运算符重载:运算符重载是指在自定义类中,通过实现特殊方法,使得类的对象可以支持内置运算符的操作。Python中的很多运算符,例如+-*/==等,都可以通过特殊方法进行重载。通过重载运算符,你可以定义类对象在使用这些运算符时的行为。

1、动作重载原理

Python数据类型-LMLPHP

三、案例

        假设我们要创建一个名为Vector的类,用于表示二维向量。我们希望能够对向量进行加法和减法操作,并且能够比较两个向量是否相等。

首先,我们定义Vector类并实现特殊方法:

class Vector:
    def __init__(self, x, y) -> None:
        self.x = x
        self.y = y

    def __add__(self, other) -> "Vector":
        if isinstance(other,Vector):
            return Vector(self.x + other.x, self.y + other.y)
        else:
            raise

    def __sub__(self, other) -> "Vector":
        return Vector(self.x - other.x, self.y - other.y)

    def __eq__(self, other) -> bool:
        return self.x == other.x and self.y == other.y

现在我们可以创建Vector对象,并进行运算符重载的操作:

# 创建两个向量
v1 = Vector(1, 2)
v2 = Vector(3, 4)

# 加法操作
result_add = v1 + v2
print(result_add.x, result_add.y)  # 输出:4 6

# 减法操作
result_sub = v1 - v2
print(result_sub.x, result_sub.y)  # 输出:-2 -2

# 相等比较
print(v1 == v2)  # 输出:False

        在上面的例子中,我们定义了Vector类,并在其中实现了__add____sub____eq__等特殊方法。通过这些特殊方法,我们可以实现向量的加法、减法和比较操作,使得Vector对象可以支持内置运算符的操作。

第六章、int类型

一、概述

1、int类型所占的字节数为4字节或者8字节,默认值为0

        在 Python 中,int 类型通常占据的字节数取决于操作系统和计算机架构。在大多数情况下,int 类型占据的字节数为4个字节(32位)或8个字节(64位)。

        在 Python 3.x 版本中,int 类型的默认值为0。这意味着如果你创建一个整数类型的变量而没有为其赋值,它将默认为0。

例如:

print(int()) #0

2、int类型取值范围:取决于内存

        在Python中,int类型的整数没有固定的大小限制。它可以表示任意大的整数,取决于你的系统内存大小。Python会自动根据需要来分配内存,以便存储所需的整数。

        总结:int类型是Python中用于表示整数数值的内置数据类型。它没有固定的大小限制,可以表示任意大的整数。整数支持常见的运算和转换,是Python中非常常用和重要的数据类型。

3、整数运算

        int类型支持常见的整数运算,包括加法、减法、乘法和除法。在进行整数运算时,如果结果是整数,将返回int类型的整数;如果结果是浮点数,将返回float类型的浮点数。 

4、不可变数据类型

        Python的整数类型是一个封装了整数的类,这意味着整数是不可变的。每次对整数进行运算时,都会创建一个新的整数对象,而不会修改原始整数对象。这也使得整数在多线程环境中是线程安全的。

二、整数的表示(默认为十进制)

1、十进制

        整数在Python中以十进制的形式表示,默认情况下没有前导零。例如,42-100都是int类型的整数。

2、十六进制

3、八进制

4、二进制

#默认为十进制
print(10) #10
#十六进制
print(0x10) #16
#八进制
print(0o10) #8
#二进制
print(0b10) #2

三、int类型是封装了整数的类(class int)

要理解整数是封装了整数的类,可以考虑以下例子:

# 创建一个整数对象
x = 42

# 检查x的类型
print(type(x))  # 输出:<class 'int'>

        在这个例子中,我们创建了一个整数x,然后使用type()函数检查x的类型。输出结果显示x的类型是<class 'int'>,表示xint类的一个实例。

        因为整数是类的实例,所以整数具有类的特性和方法。例如,我们可以使用dir()函数来查看整数对象的属性和方法:

print(dir(x))

        输出结果将包含一系列整数对象可以调用的方法和属性。这些方法和属性允许我们在整数上进行各种操作,例如进行算术运算、位运算等。

        这种将整数封装在类中的设计是Python中的一种对象导向的编程(Object-Oriented Programming,简称OOP)的概念。Python中的很多数据类型实际上都是类的实例,包括整数、浮点数、字符串、列表等。这使得Python非常灵活和强大,可以通过调用类的方法来操作不同类型的数据。

        总结:在Python中,整数是封装在int类中的对象。虽然我们将其视为基本数据类型,但实际上它是int类的实例,具有类的特性和方法。这种设计使得整数具有更多的灵活性,并让Python支持面向对象的编程范式。

四、常用方法

        在Python中,int类型是整数的数据类型。除了基本的算术运算外,int类型还提供了一些常用的方法来对整数进行操作和转换。下面是一些常用的int类型方法:

1、bit_length(): 返回整数的二进制表示的位数(不包括符号位)

num = 42
print(num.bit_length())  # 输出:6(42的二进制表示是'101010',有6位)

2、to_bytes(length, byteorder, signed): 将整数转换为字节序列。

length指定期望的字节数,byteorder指定字节序('big'表示大端序,'little'表示小端序),signed指定是否要包含符号位。

num = 2021
bytes_representation = num.to_bytes(2, byteorder='big')
print(bytes_representation)  # 输出:b'\x07\xe5'(2021的大端序字节表示)

3、from_bytes(bytes, byteorder, signed): 将字节序列转换为整数

bytes_representation = b'\x07\xe5'
num = int.from_bytes(bytes_representation, byteorder='big')
print(num)  # 输出:2021(将大端序字节转换回整数2021)

4、conjugate()realimag 方法

complex_num = 2 + 3j
print(complex_num.conjugate())  # 输出:(2-3j)(复数2 + 3j 的共轭为 2 - 3j)
print(complex_num.real)  # 输出:2(复数的实部)
print(complex_num.imag)  # 输出:3(复数的虚部)

5、__abs__(): 返回整数的绝对值(abs() 调用)

num = -10
print(abs(num))  # 输出:10(-10 的绝对值是 10)

6、__add__(other): 实现整数与其他对象的加法操作(+ 调用)

class MyInt:
    def __init__(self, value:int):
        self.value = value
    #MyInt类型提示前向引用,需要加引号
    def __add__(self, other:Any) -> "MyInt":
        if isinstance(other, MyInt):
            return MyInt(self.value + other.value)
        else:
            raise

num1 = MyInt(5)
num2 = MyInt(10)
#使用+运算符时,会自动调用__add__方法
result = num1 + num2
print(result.value)  # Output: 15

7、__sub__(other): 实现整数与其他对象的减法操作(- 调用)

class MyIntSub(object):

    #重写父类object的方法
    def __init__(self,value:int):
        self.value = value

    def __sub__(self, other: "MyIntSub") -> "MyIntSub":
        if isinstance(other,MyIntSub):
            return MyIntSub(self.value - other.value)
        else:
            raise

a:MyIntSub = MyIntSub(10)
b:MyIntSub = MyIntSub(5)
#使用 - 运算符时,会自动调用__sub__方法
result:MyIntSub = a - b
print(result.value) #输出5

8、__mul__(other): 实现整数与其他对象的乘法操作(* 调用)

class MyIntMul(object):
    #构造方法
    def __init__(self,value:int) -> None:
        self.value = value

    def __mul__(self, other:"MyIntMul") -> "MyIntMul":
        if isinstance(other,MyIntMul):
            return MyIntMul(self.value * other.value)
        else:
            raise

a:MyIntMul = MyIntMul(10)
b:MyIntMul = MyIntMul(3)
#使用乘法 * 时会自动调用 __mul__方法
result:MyIntMul = a * b
print(result.value) #30

9、__floordiv__(other): 实现整数与其他对象的整数除法操作(取整操作 //调用)

class MyIntFloordiv(object):
    #构造方法
    def __init__(self,value:int) -> None:
        self.value = value

    def __floordiv__(self, other: "MyIntFloordiv") -> "MyIntFloordiv":
        if isinstance(other,MyIntFloordiv):
            return MyIntFloordiv(self.value // other.value)
        else:
            raise

a: MyIntFloordiv = MyIntFloordiv(10)
b: MyIntFloordiv = MyIntFloordiv(3)
#当使用//运算符时,会自动调用__floordiv__方法
result: MyIntFloordiv = a // b
print(result.value)

10、__truediv__(other): 实现整数与其他对象的真除法操作(保留小数除法   / 调用)。

class MyIntTruediv(object):
    #构造方法
    def __init__(self,value):
        self.value = value

    def __truediv__(self, other:"MyIntTruediv") -> "MyIntTruediv":
        if isinstance(other,MyIntTruediv):
            return MyIntTruediv(self.value / other.value)
        else:
            raise

a:MyIntTruediv = MyIntTruediv(10)
b:MyIntTruediv = MyIntTruediv(3)
#当使用/运算符时,会自动调用__truediv__方法
result:MyIntTruediv = a / b
print(result.value) #3.3333333333333335

11、__mod__(other): 实现整数与其他对象的取模操作(取余数操作  % 调用)

class MyIntMod(object):
    #构造方法
    def __init__(self,value:int) -> None:
        self.value = value

    def __mod__(self, other:"MyIntMod") -> "MyIntMod":
        if isinstance(other,MyIntMod):
            return MyIntMod(self.value % other.value)
        else:
            raise
        # pass

a:MyIntMod = MyIntMod(10)
b:MyIntMod = MyIntMod(3)
#当使用%运算符时,会自动调用__mod__方法
result:MyIntMod = a % b
print(result.value) #1

12、__pow__(other, modulus): 实现整数的幂运算(** 调用)

参数modulus可选,指定计算幂时的模数。

class MyIntPow(object):
    #构造方法
    def __init__(self,value:...) -> None:
        self.value = value

    def __pow__(self, power:"MyIntPow", modulo=None) ->"MyIntPow":
        if isinstance(power,MyIntPow):
            return MyIntPow(self.value ** power.value)
        else:
            raise

a:MyIntPow = MyIntPow(2)
b:MyIntPow = MyIntPow(3)
#当使用**运算符时,会自动调用__pow__方法
result:MyIntPow = a ** b
print(result.value) #8

 13、__round__( ndigits: SupportsIndex = ...) -> int 用于执行浮点数的四舍五入操作,并返回最接近的整数(round方法调用)

round(number[, ndigits])

参数说明:

  • number:表示要进行四舍五入的数字。
  • ndigits(可选):表示要保留的小数位数,默认为 0。如果省略 ndigits 参数,则 round() 函数会将 number 四舍五入到最接近的整数。

round() 函数的工作原理如下:

  • 如果 ndigits 参数为正数,则 number 会四舍五入到小数点后的第 ndigits 位。例如,round(3.14159, 2) 返回 3.14,保留两位小数。
  • 如果 ndigits 参数为负数,则 number 会四舍五入到整数的个位、十位等位置上。例如,round(12345, -2) 返回 12300,保留到最近的百位。

使用示例:

result1 = round(3.14159)  # 不指定 ndigits,默认四舍五入到整数
print(result1)  # 输出:3

result2 = round(3.14159, 2)  # 四舍五入到小数点后两位
print(result2)  # 输出:3.14

result3 = round(12345, -2)  # 四舍五入到最近的百位
print(result3)  # 输出:12300

        这些是int类型的一些常用方法,可以帮助你对整数进行各种操作和转换。需要注意的是,int类型是不可变类型,因此这些方法并不会修改原始的整数对象,而是返回一个新的结果。

14、__divmod__(self, x: int) -> tuple[int, int] 返回一个元组,其中包含除法的商和取模的结果

语法:

def __divmod__(self, other):
        """
        Return the tuple (x // y, x % y).
        """
        pass

其中,self 表示当前的整数对象,other 表示除数。

使用示例:

x = 10
y = 3
quotient, remainder = divmod(x, y)

print(quotient)  # 输出:3,表示整数除法的结果
print(remainder)  # 输出:1,表示取模的结果

print(divmod(10,3)) #(3, 1)

        在上面的示例中,我们使用了 Python 内置函数 divmod() 来执行整数除法和取模操作,并将结果分别赋值给 quotientremainder 变量。

        实际上,divmod(x, y) 等价于 x.__divmod__(y),也就是调用 x 这个整数对象的 __divmod__ 方法。该方法会返回整数除法的商和取模的结果,以一个元组的形式返回。

__divmod__ 方法在整数对象中的实现是由 Python 解释器完成的,通常不需要我们手动定义。它是一种特殊方法,用于支持内置函数 divmod() 和其他相关操作。

五、int类型转换

         Python提供了各种函数来在不同进制和数据类型之间进行整数转换。例如,int()函数用于将其他类型的数据转换为整数,bin()oct()hex()函数用于将整数转换为二进制、八进制和十六进制字符串。

1、int(x)

@overload
    def __new__(cls: Type[_T], x: str | bytes | SupportsInt | SupportsIndex | _SupportsTrunc = ...) -> _T: ...

2、int(x, base=10)

@overload
    def __new__(cls: Type[_T], x: str | bytes | bytearray, base: SupportsIndex) -> _T: ...
  • x:待转换的参数,可以是字符串、浮点数、布尔值或其他支持转换为整数的类型。
  • base(可选参数):表示待转换的进制,默认为10,可选的进制参数base可以用于指定字符串的进制,例如:
    • base = 16 表示解析16进制字符串转换为10进制整数
    • base = 8 表示解析8进制字符串转换为10进制整数
    • base = 2 表示解析2进制字符串转换为10进制整数

2.1、int()函数将其他数据类型转换为int类型原理

2.2、__int__方法解析

        在 Python 中,__int__() 是一个特殊方法(也称为魔术方法),用于自定义类的实例对象在转换为整数时的行为。当我们将一个对象转换为整数时,Python 解释器会自动调用该对象的 __int__() 方法,从而实现对象到整数的转换。

__int__() 方法的语法如下:

class MyClass:
    def __int__(self):
        """
        Custom implementation for converting the object to an integer.
        """
        pass

        在上面的示例中,MyClass 是一个自定义类,其中定义了 __int__() 方法。我们可以在这个方法中自定义对象到整数的转换逻辑。

使用示例:

class MyInt:
    def __init__(self, value):
        self.value = value

    def __int__(self):
        return self.value

num = MyInt(42)
result = int(num)
print(result)  # 输出:42

        在上面的示例中,我们定义了一个名为 MyInt 的类,其中包含 __init__()__int__() 方法。__init__() 用于初始化对象的值,__int__() 则返回对象的整数值。当我们调用内置函数 int() 来将 MyInt 类的对象转换为整数时,Python 解释器会自动调用 __int__() 方法,从而获取对象的整数值并返回。

        需要注意的是,__int__() 方法应该返回一个整数类型的值,否则会引发 TypeError。这个方法的主要用途是在自定义类的实例在转换为整数时提供一个合适的行为。

2.3、int()函数可转换的数据类型

  • 浮点数int()将截断浮点数的小数部分,返回整数部分。例如,int(3.14)将返回3

  • 布尔值True会转换为整数1False会转换为整数0

  • 字符串(具有数字的字符串)int()会尝试将字符串解析为整数。如果字符串不符合整数格式,将会抛出ValueError异常。可选的进制参数base可以用于指定字符串的进制,例如base=16表示解析16进制字符串。

# 将字符串转换为整数
num_str = "123"
num_int = int(num_str)
print(num_int)  # 输出: 123

# 指定进制进行转换
hex_str = "1A"
hex_int = int(hex_str, base=16)
print(hex_int)  # 输出: 26

# 转换浮点数(小数部分将被截断)
float_num = 3.14
int_num = int(float_num)
print(int_num)  # 输出: 3

# 转换布尔值
bool_val = True
int_val = int(bool_val)
print(int_val)  # 输出: 1

请注意,在使用int()函数时,始终确保提供的参数是合法且可转换为整数,以避免出现异常。

3、将整数转换为对应的二进制、八进制和十六进制字符串表示形式

        在 Python 中,bin()oct()hex() 是内置函数,而不是特殊方法(魔术方法)。它们用于将整数转换为对应的二进制、八进制和十六进制字符串表示形式。这些函数是 Python 语言提供的便捷工具,用于进行整数与进制字符串之间的转换,而不是用于在类中定义对象的行为。

        与特殊方法(例如 __str____add__ 等)不同,这些内置函数并不是用于在类的定义中实现自定义行为的。它们是 Python 内置的功能,设计用于特定用途的实用函数,如整数进制转换、格式化输出等。

例如,bin() 函数用于将整数转换为二进制字符串:

x = 10
binary_string = bin(x)
print(binary_string)  # 输出:'0b1010'

        这里我们并没有在类的定义中使用 __bin__ 这样的特殊方法,而是直接使用了内置函数 bin() 来完成整数转换的操作。

        特殊方法(魔术方法)主要用于自定义类的行为和操作,例如重载加法运算、字符串表示等。这些方法在类的定义中以特殊的双下划线命名,用于在对象执行特定操作时由 Python 解释器自动调用。而 bin()oct()hex() 等函数是 Python 内置函数库提供的标准功能,是由解释器在内部实现的。因此,它们并不需要像特殊方法那样在类的定义中实现。

1、bin() 函数

  • 用于将整数转换为二进制字符串。
  • 语法:bin(x)
  • 参数 x 是一个整数,返回一个以 '0b' 开头的二进制字符串,其中 '0b' 表示二进制数的前缀。
  • 示例:
x = 10
binary_string = bin(x)
print(binary_string)  # 输出:'0b1010'

2、oct() 函数

  • 用于将整数转换为八进制字符串。
  • 语法:oct(x)
  • 参数 x 是一个整数,返回一个以 '0o' 开头的八进制字符串,其中 '0o' 表示八进制数的前缀。
  • 示例:
x = 10
octal_string = oct(x)
print(octal_string)  # 输出:'0o12'

3、hex() 函数:

  • 用于将整数转换为十六进制字符串。
  • 语法:hex(x)
  • 参数 x 是一个整数,返回一个以 '0x' 开头的十六进制字符串,其中 '0x' 表示十六进制数的前缀。
  • 示例:
x = 10
hexadecimal_string = hex(x)
print(hexadecimal_string)  # 输出:'0xa'

        这些函数通常用于整数的进制转换和格式化输出。需要注意的是,这些函数返回的结果都是字符串类型。如果需要将二进制、八进制或十六进制字符串转换回整数,可以使用 int() 函数,并指定相应的进制基数参数。例如:

binary_string = '0b1010'
x = int(binary_string, 2)  # 将二进制字符串转换为整数
print(x)  # 输出:10

第七章、float类型

一、概述

        在 Python 中,float 类型是一种浮点数类型,用于表示实数(包括小数和整数)。浮点数是一种近似表示的数值类型,可以表示非常大或非常小的数,以及包含小数部分的数值。浮点数在计算机中用于处理需要更高精度的数学计算和科学计算等场景。

1、float类型所占的字节数为8字节,默认值为0

以下是一个示例:

# 浮点数类型占据8个字节(64位)
x = 1.23
y = 3.14
print(x)  # 输出:1.23
print(y)  # 输出:3.14

# 浮点数类型默认值为0.0
z = float()
print(z)  # 输出:0.0

        在上面的示例中,我们定义了两个浮点数变量 xy,它们分别赋值为 1.23 和 3.14。我们还定义了一个没有明确赋值的浮点数变量 z,它的默认值为 0.0。

2、float类型取值范围

        在 Python 中,超出浮点数范围的数值将被表示为正或负的无穷大(inf-inf),或者被表示为特殊的非数值(NaN,表示"not a number")。例如:

# 表示正无穷大
positive_inf = float("inf")
print(positive_inf) #inf

# 表示负无穷大
negative_inf = float('-inf')
print(negative_inf) #-inf

# 表示非数值
nan = float("nan")
print(nan) #nan

以下是一个示例,展示浮点数的取值范围和一些特殊的浮点数表示:

# 浮点数的取值范围
min_float = -1.7976931348623157e308
max_float = 1.7976931348623157e308

print(min_float)  # 输出:-1.7976931348623157e+308
print(max_float)  # 输出:1.7976931348623157e+308

# 特殊的浮点数表示
print(float('inf'))  # 输出:inf
print(float('-inf'))  # 输出:-inf
print(float('nan'))  # 输出:nan

3、浮点数运算

浮点数可以进行数学运算,包括加减乘除等操作:

num1 = 2.5
num2 = 1.3

result = num1 + num2
print(result)  # 输出: 3.8

result = num1 * num2
print(result)  # 输出: 3.25

4、精度问题

浮点数的有限精度可能导致一些精度问题,例如:

num1 = 0.1
num2 = 0.2

result = num1 + num2
print(result)  # 输出: 0.30000000000000004

这是由于0.1和0.2在二进制浮点数中无法精确表示,导致了微小的舍入误差。

如果您需要高精度的数值计算,可以使用decimal模块中的Decimal类型,它提供更高的精度,并避免了浮点数的舍入误差。

5、不可变数据类型

  float类型是Python中的不可变数据类型,不可变数据类型是指一旦创建后,其值不能被修改,如果对其进行操作或修改,会生成一个新的对象。float类型属于不可变数据类型,这意味着一旦创建了一个浮点数对象,就无法直接修改其值。

让我们通过一些例子来说明不可变数据类型的特点:

# 创建一个浮点数对象
num_float = 3.14

# 尝试修改浮点数的值,会生成一个新的对象
num_float = 2.71

# 上面的操作不是直接修改原始对象,而是创建了一个新的浮点数对象

二、浮点数的表示:只能以十进制表示

   float类型在Python中用于表示浮点数,它是一种有限精度的数据类型。浮点数采用二进制浮点数表示方式,通常遵循IEEE 754标准。

        浮点数的表示并不直接使用二进制、八进制或十六进制的形式,而是采用一种叫做"双精度浮点数"的格式。这种格式使用二进制科学计数法(二进制指数和尾数),将浮点数表示为一个符号位、指数位和尾数位的组合。

        这种表示方式使得浮点数可以在广泛的数值范围内表示非常大和非常小的数值,但也导致了一些精度问题。由于浮点数的有限精度,有些数值无法在二进制浮点数中精确表示,这会引起舍入误差。

        这就是为什么在进行浮点数计算时,特别是涉及到比较运算时,可能会出现一些意外的结果。为了避免这种情况,在需要高精度计算时,可以使用decimal模块中的Decimal类型,它提供更高的精度。

当我们写一个浮点数时,它默认为十进制数。例如:

decimal_float = 3.14
print(decimal_float)  # 输出: 3.14

         如果您有一个十六进制数,并希望将其转换为浮点数,您需要先将其转换为十进制数,然后再创建一个float类型的对象。

hex_string = "0x1A"
decimal_number = int(hex_string, 16)
float_number = float(decimal_number)
print(float_number)  # 输出: 26.0

         在这里,我们首先使用int()将十六进制字符串"0x1A"转换为十进制整数26,然后使用float()将整数26转换为浮点数26.0

三、float类型是封装了浮点数的类(class float)

        在Python中,float是表示浮点数的内置数据类型,也是一个内置类。它用于存储带有小数部分的浮点数值,并在计算机内部以IEEE 754标准的双精度浮点数格式进行表示。

        浮点数由一个符号位、指数位和尾数位组成,可以表示非常大和非常小的数值。然而,由于浮点数的有限精度,它可能无法精确表示一些数值,可能会引起舍入误差。

        在Python中,您可以使用float()构造函数或直接赋值来创建浮点数对象。以下是一些示例:

# 使用 float() 构造函数创建浮点数对象
num_float = float(3.14)
print(num_float)  # 输出: 3.14

# 直接赋值创建浮点数对象
# 自动装箱机制
pi = 3.14159
print(pi)  # 输出: 3.14159


#float类型创建实例对象及初始化过程
a = float.__new__(float,123)
a.__init__()
print(a) #123.0

四、float类型的科学计数法

        在Python中,float类型的科学表示法指的是浮点数的科学计数法(scientific notation)。科学计数法用于表示非常大或非常小的数值,并且可以简洁地表示这些数值。

科学计数法的表示形式如下:

        其中,a 是一个介于 1.0(包含)与 10.0(不包含)之间的数,称为尾数或有效数字(significand),b 是一个整数,表示指数。

        在浮点数的科学计数法中,尾数可以是整数或小数,指数可以是正整数或负整数。指数为正数时表示非常大的数,指数为负数时表示非常小的数。

Python中的浮点数可以用科学计数法来表示。以下是一些示例:

# 1.0 x 10^3 = 1000.0
num1 = 1e3
print(num1)  # 输出: 1000.0

# 3.14 x 10^-2 = 0.0314
num2 = 3.14e-2
print(num2)  # 输出: 0.0314

        在这些示例中,1e3 表示 1.0 乘以 10 的 3 次方,即 1000.0。而 3.14e-2 表示 3.14 乘以 10 的负 2 次方,即 0.0314。

使用科学计数法,可以更清晰地表示非常大或非常小的数值,有助于简化数据的表示和处理。

五、常用方法

1、as_integer_ratio(): 将浮点数表示为分数的形式,返回一个元组 (numerator, denominator)

num_float = 3.14
ratio = num_float.as_integer_ratio()
print(ratio)  # 输出: (7070651414971679, 2251799813685248)

2、is_integer(): 检查浮点数是否表示一个整数

num_float = 3.0
result = num_float.is_integer()
print(result)  # 输出: True

num_float = 3.14
result = num_float.is_integer()
print(result)  # 输出: False

3、hex(): 将浮点数表示为十六进制字符串

num_float = 3.14
hex_string = num_float.hex()
print(hex_string)  # 输出: '0x1.91eb851eb851fp+1'

六、float类型转换

        在 Python 中,float 类型的转换主要是将其他数据类型转换为 float 类型或者将 float 类型转换为其他数据类型。常见的 float 类型转换包括以下几种:

1、将int类型转换为float类型

# 从整数转换为 float
num_int = 10
float_num = float(num_int)
print(float_num) #10.0

2、将字符串(具有数字的字符串)转换为float类型

# 从字符串转换为 float
num_str = "3.14"
float_num = float(num_str)
print(float_num) #3.14

3、将布尔类型转换为 float 类型(True 转换为 1.0,False 转换为 0.0)

bool_value = True
float_value = float(bool_value)  # 结果为 1.0

bool_value = False
float_value = float(bool_value)  # 结果为 0.0

4、将其他类型转换为 float 类型时需要注意可能引发异常的情况

# 转换非法字符串为 float,会引发 ValueError
num_str = "hello"
try:
    float_num = float(num_str)
except ValueError as e:
    print("Error:", e) #Error: could not convert string to float: 'hello'

        需要注意的是,使用 float() 函数进行转换时,如果转换失败(例如字符串中包含非法字符),将会引发 ValueError 异常,因此在进行 float 类型转换时最好使用 try-except 块来处理异常情况。

七、int和float类型之间互相转换

1、自动类型转换

# int 自动转换为 float
x = 10
y = 3.14
result = x + y
print(result)  # 输出 13.14

2、强制类型转换

# float 不会自动转换为 int
a = 5.7
b = 3
result2 = a + b
print(result2)  # 输出 8.7,结果为 float 类型

c = int(a) + b
print(c)  # 输出 8,结果为 int 类型,使用 int() 函数显式进行转换

         总结:Python 中 int 类型可以隐式转换为 float 类型,但是 float 类型不能隐式转换为 int 类型。如果需要将 float 类型转换为 int 类型,可以使用 int() 函数进行显式转换。

3、多种数据做混合运算,先转换成容量最大的那种类型再做运算,最终结果也为容量最大的那种类型

        当进行混合类型运算时,Python 会根据运算符的优先级和操作数的类型进行隐式类型转换。如果参与运算的操作数中包含 float 类型,那么整个运算结果会被转换为 float 类型。这意味着 int 类型会自动转换为 float 类型,但反过来 float 类型不会自动转换为 int 类型。

第八章、bool类型

一、概述

1、bool类型所占字节数为1字节,默认值为False

        在 Python 中,bool 类型占用的字节数是 1 字节。bool 类型表示布尔值,只有两个取值:True 和 False。

        默认情况下,bool 类型的默认值是 False。这意味着在创建一个新的 bool 类型变量时,如果没有明确赋值为 True,则它将自动被设置为 False。例如:

# 默认情况下,b1 被设置为 False
b1 = bool()
print(b1)  # 输出 False

# 显式赋值为 True
b2 = True
print(b2)  # 输出 True

2、bool类型只有True和False两个值,支持隐式类型转换

        这两个取值在条件判断和逻辑运算中起着重要的作用,例如在 if 语句中,条件为 True 时执行相应的代码块,条件为 False 时则跳过代码块。在逻辑运算中,True 和 False 可以进行与、或、非等运算。

以下是一些使用 bool 类型取值的示例:

# 条件判断示例
x = 10
y = 20
if x < y:
    print("x is less than y")  # 输出 x is less than y

# 逻辑运算示例
a = True
b = False
print(a and b)  # 输出 False
print(a or b)   # 输出 True
print(not a)    # 输出 False
# 隐式类型转换
print(bool(0))          # 输出 False
print(bool(10))         # 输出 True
print(bool(""))         # 输出 False
print(bool("Hello"))    # 输出 True
print(bool([]))         # 输出 False
print(bool([1, 2, 3]))  # 输出 True
print(bool({}))         # 输出 False
print(bool({"a": 1}))   # 输出 True
print(bool(None))       # 输出 False

 3、真值测试:__bool__()方法

        真值测试:在条件判断和逻辑运算中,Python 会对值进行真值测试。除了上述隐式类型转换规则外,还有一些对象的特殊方法(如 __bool__()__len__() 等)可以自定义对象的真值测试行为。

# 真值测试
class MyClass:
    def __bool__(self):
        return False

obj = MyClass()
print(bool(obj))  # 输出 False

4、bool类型运算

在 Python 中,bool 类型可以进行运算,也可以参与逻辑运算和比较运算。

        运算:bool 类型在运算时会被隐式转换为整数类型。True 被转换为 1,False 被转换为 0。这样,我们可以对 bool 类型的变量进行数值运算,例如加法、减法、乘法等。当进行数值运算时,True 视为 1,False 视为 0。

print(True + True)   # 输出 2
print(True - False)  # 输出 1
print(True * 10)     # 输出 10
print(False * 5)     # 输出 0

逻辑运算:bool 类型可以参与逻辑运算,包括与(and)、或(or)、非(not)等运算。

print(True and False)  # 输出 False
print(True or False)   # 输出 True
print(not True)        # 输出 False

比较运算:bool 类型也可以参与比较运算,例如与数值类型的比较。

print(True == 1)   # 输出 True
print(False != 0)  # 输出 False

        需要注意的是,虽然 bool 类型可以进行运算,但在实际应用中,通常我们更多地使用 bool 类型进行条件判断和逻辑判断,而较少将其用于数值运算。数值运算主要针对数值类型,而不是 bool 类型。

5、不可变数据类型

bool 类型在 Python 中属于不可变数据类型。不可变数据类型是指一旦创建后,其值就不能再被修改。对于 bool 类型,只有两个取值,True 和 False,一旦创建了一个 bool 类型的变量,其值就固定为 True 或 False,无法改变。

x = True
y = False

x = False  # 这里实际上是创建了一个新的 bool 对象,并将 x 的引用指向了该对象

        在上面的例子中,当执行 x = False 时,实际上是创建了一个新的 bool 对象,并将 x 的引用指向了该对象,原来的 True 对象并没有被修改,而是被丢弃了。

        因为 bool 类型是不可变的,所以在进行逻辑运算或条件判断时,我们可以放心地使用 bool 类型的值,因为它们不会被意外地改变。

二、bool类型是封装了的类(class bool(int))

        因为 bool 类型是继承自 int 类型的,所以它继承了 int 类型的一些特性和方法。例如,我们可以将 True 和 False 当作整数来使用,进行加减乘除等运算。True 的整数值是 1,False 的整数值是 0。

三、bool表达式(底层调用__bool__方法)

# 布尔表达式示例
x = 10
y = 5
is_greater = x > y  # 结果为 True

四、 bool类型用于条件语句


# 条件语句示例
num = 7
if num % 2 == 0:
    print("偶数")
else:
    print("奇数")

五、bool类型用于循环


# 布尔值用于循环示例
is_running = True
count = 0
while is_running:
    count += 1
    if count == 10:
        is_running = False
print("循环结束")

六、常用方法

        在 Python 中,bool 类型并没有自己独有的方法,因为它是 int 类型的子类,继承了 int 类型的所有方法。实际上,bool 类型的对象可以当作整数来使用,所以可以使用 int 类型的方法对 bool 类型的对象进行操作。

以下是一些常用的 int 类型方法,在 bool 类型上同样适用:

  1. __bool__() 方法:用于返回 bool 类型对象的布尔值 True 或 False。通常在条件判断中使用。

  2. __eq__(other) 方法:用于判断两个 bool 类型对象是否相等。

  3. __ne__(other) 方法:用于判断两个 bool 类型对象是否不相等。

  4. __int__() 方法:将 bool 类型对象转换为整数值 1 或 0。

  5. __str__() 方法:返回 bool 类型对象的字符串表示,即 'True' 或 'False'。

示例:

x = True
y = False

# 使用 bool 类型对象进行条件判断
if x:
    print("x is True")
else:
    print("x is False")

# 使用 int 类型的方法对 bool 类型对象进行操作
z = int(x)
print(z)  # 输出:1

# 判断两个 bool 类型对象是否相等
print(x == y)  # 输出:False

# 将 bool 类型对象转换为字符串
print(str(x))  # 输出:'True'

        需要注意的是,bool 类型是不可变类型,一旦创建后,其值不能被修改。因此,在实际使用中,我们通常不会对 bool 类型对象调用任何修改值的方法。

七、bool类型转换(bool()函数,显示类型转换)

print(bool(0)) #False
print(bool(0.0)) #False
print(bool("")) #False
print(bool([])) #False
print(bool(())) #False
print(bool({})) #False
print(bool(None)) #False
12-31 11:52