Python数据类型

本文围绕Python展开,介绍了数据类型,包括基本数据类型(如整数、浮点数等)的不可变原理及案例,引用数据类型(如列表、字典等)的可变原理。还阐述了None类型的用法,以及int、float、bool、str等类型的特点、常用方法和类型转换,同时提及Python中类似Java StringBuilder类的实现。

 第四章、数据类型

        数据类型的作用:程序当中有很多数据,每一个数据都是有相关类型的,不同数据类型的数据占用空间大小不同。数据类型的作用就是指导PVM在运行程序的时候给数据在堆内存中分配多大的内存空间。

        输出在控制台的都是字符串类型,会自动调用对象的__str__()方法

     在 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):使用花括号 {} 表示,可以添加、删除元素。

        需要注意的是,Python 是一种动态类型语言,变量的类型是根据赋值的数据类型自动确定的。无论是基本数据类型还是引用数据类型,都可以使用简单的赋值语句创建变量,并在程序中使用它们。

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空值对象是NoneType类的唯一实例对象

NoneType类是所有类的子类,因此可给任意数据类型赋值

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

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

1、None类型用法

1、初始化变量

当你需要声明一个变量,但是还没有确切的值时,可以将其初始化为 None

x = None
2、返回空值

在函数中,如果没有明确的返回值,或者在某种情况下不需要返回任何值,可以使用 return None 来返回空值。

def do_something():
    # 执行一些操作,但不需要返回值
    return None

因为NoneType类型是在Python解释器中存在的,并不是真正的类型,所以使用None来表示NoneType类型,来指代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、默认参数值

在函数定义时,可以将参数的默认值设置为 None,以允许调用函数时不传递该参数。

def greet(name=None):
    if name is None:
        return "Hello, Guest!"
    else:
        return f"Hello, {name}!"

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

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

       None 是一个特殊的对象,它是Python中唯一的 NoneType 对象。它不同于空字符串 ""、空列表 [] 或空字典 {},这些都是不同类型的对象,表示不同的含义。

        在使用 None 时,要小心避免与其他类型的数据混淆。通常,当你需要表示空值或缺失的值时,可以使用 None

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 并不是可以自由创建的对象或类型,而是内置到语言中的特殊值和类型。

3、使用is判断None

        在 Python 中,使用 is 操作符来判断变量是否为 None 是因为 is 操作符比 == 操作符更准确地检查对象的身份标识。在 Python 中,每个对象都有一个唯一的身份标识,可以通过 id() 函数获取。

考虑以下示例:

a = None
b = None

# 使用 is 操作符判断身份标识
print(a is b)  # 输出: True

# 使用 == 操作符判断值是否相等
print(a == b)  # 输出: True

        在上述例子中,ab 都是 None,因此它们的值相等。使用 == 操作符可以检查两个对象的值是否相等,这对于检查 None 是有效的。然而,使用 is 操作符更常用,因为它不仅检查值是否相等,还检查对象的身份标识是否相同。

        在 Python 中,None 是一个特殊的单例对象,表示空值或缺失值。因为 None 是单例对象,所以使用 is 操作符可以更精确地检查变量是否引用相同的 None 对象,而不仅仅是值是否相等。

        总体来说,对于 None 的判断,推荐使用 is 操作符,除非你确切地知道你想要检查值是否相等而不关心对象的身份标识。

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

        Python 中的所有数据都是对象,无论是基本数据类型还是引用数据类型。基本数据类型虽然是不可变的,但在进行操作时,可能会创建新的对象,这是因为 Python 中的对象都是按值传递的。而引用数据类型的内容可以在原对象上修改,因为这些对象在内存中是可变的。

四、判断数据类型运算符

变量名是没有数据类型的,只有变量值有数据类型,判断均为变量值的数据类型

1、type() -> object  内置类

type() 函数可以返回给定对象的类型。它可以用于判断变量、常量或表达式的数据类型。

例如:

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

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

# 也可以使用type来判断类型
print(type(2) == int) # True

2、isinstance() ->bool 内置函数

isinstance() 函数用于检查一个对象是否属于指定的数据类型。它可以用于判断变量的类型是否为特定的类型或其子类。返回bool类型

例如:

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() 经常用于检查函数参数的数据类型或进行条件判断,以确保正确处理不同类型的数据。根据具体需求,您可以选择合适的方式来判断数据的类型。

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

一、概述

类似于动作重载,虽然对象A和对象B有同样名称的动作,但是由于对象不同,动作的结果也就不同,这就是动作重载。

主要用于自定义对象和类的属性和行为。

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

二、特殊方法

1、定义

       特殊方法(也称为魔术方法或双下划线方法)是用于定义类在特定操作下的行为。这些特殊方法都有固定的命名格式,例如 __init____add____str__ 等。它们在类的定义中具有特殊的含义,当对象执行相关操作时,Python 解释器会自动调用相应的特殊方法

2、以实例方法为主

以实例方法为主,也有少部分静态方法(比如__new__)

3、作用理解

类似于接口,也可理解为接口方法,只要类中定义了这些特殊方法时,就表示该类的实例对象或者该类有对应特殊方法的功能(动作),Python会在适当的时候自动调用这些方法

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

 像__abs__ 这样的方法都有什么作用,怎么调用,为什么这么奇怪

__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__这个方法的话,就表示该对象可以求绝对值了是吧

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

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

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

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

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

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

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

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

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

通过符号调用

  • 以__add__()方法为例:
    • 实例对象a + 实例对象b  ==》自动调用  实例对象a.__add__(实例对象b)

通过方法调用

  • 以__round__()方法为例
    • round(实例对象a, 实例对象b) ==》 自动调用  实例对象a.__round__(实例对象b)
  • 以__abs__()方法为例
    • abs(实例对象a) ==》 自动调用  实例对象a.__abs__()

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

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

1、动作重载原理

三、案例

        假设我们要创建一个名为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类型

Python中int类型就相当于java中的byte,short,int,long类型

一、概述

        在Python中,int(整数)类型是用于表示整数数值的数据类型。int类型是一种内置数据类型,可以用来表示正整数、负整数和零。

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

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

        在 Pyth

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值