Python面向对象(类和对象)

Python 语言在设计之初,就定位为一门面向对象的编程语言,“Python 中一切皆对象”就是对 Python 这门编程语言的完美诠释。

一、类和对象

1、类的定义

Python 类是由类头(class 类名)和类体(统一缩进的变量和函数)构成。

使用 class 关键字定义一个类,基本语法格式如下:

class 类名:
    n个类属性...
    n个类方法...

注意:

  • 类名本质上就是一个标识符,推荐见名知意,驼峰命名。
  • 类名后要紧跟冒号(:),表示告诉 Python 解释器,下面要开始设计类的内部功能了,也就是编写类属性和类方法。
  • 类定义说明文档和函数类似,需要要放到类头之后,类体之前的位置。

示例代码如下:

class MyClass:
    """一个简单的类实例"""
    name = "赵云"

    def m1(self):
        return 'hello class'

2、类构造方法

Python 类有一个名为 __init__() 的方法,该方法是一个特殊的类实例方法,称为构造方法(或构造函数)。

构造方法的作用是每当创建一个类的实例对象时,Python 解释器都会自动调用它。即该方法在类实例化时会自动调用。

手动添加构造方法的语法格式如下:

def __init__(self,...):
    代码块

注意:

  • 方法名开头和结尾各有 2 个下划线,且中间不能有空格。
  • __init__() 方法可以包含多个参数,但必须包含一个名为 self 的参数,且必须作为第一个参数。
  • 即便不手动为类添加任何构造方法,Python 也会自动为类添加一个仅包含 self 参数的默认构造方法。

示例代码如下:

class MyClass:
    """一个简单的类实例"""
    name = "赵云"

    # 构造方法
    def __init__(self):
        print("调用构造方法")
        
    def m1(self):
        return 'hello class'


# 实例化类
clazz = MyClass()

# 访问类的属性和方法
print("属性 i 为:", clazz.name)
print("调用 m1方法,输出为:", clazz.m1())

在这里插入图片描述

2.1 self 参数

Python 只是规定,无论是构造方法还是实例方法,最少要包含一个参数,并没有规定该参数的具体名称。之所以将其命名为 self(self 不是 python 关键字),只是程序员之间约定俗成的一种习惯,遵守这个约定。

self 参数的具体作用:

  • self 代表的是类的实例,代表当前对象的地址。而 self.class 则指向类。
  • self 所表示的都是实际调用该方法的对象(即谁调用该方法,那么 self 就代表谁)。

总之,无论是类中的构造函数还是普通的类方法,实际调用它们的谁,则第一个参数 self 就代表谁。
self 参数是特殊参数,无需我们手动传递它,Python 会自动传递。

3、类的实例化

创建类对象的过程,称为类的实例化。

对已定义好的类进行实例化,其语法格式如下:

类名(参数)

  • 定义类时,如果没有手动添加 __init__() 构造方法,又或者添加的__init__()中仅有一个 self 参数,则创建类对象时的参数可以省略不写。

3.1 类对象访问变量或方法

访问类中实例变量的语法格式如下:

类对象名.变量名

调用类中方法的语法格式如下:

类对象名.方法名(参数)

示例代码如下:

class MyClass:
    """一个简单的类实例"""
    name = "赵云"

    # 构造方法
    def __init__(self):
        print("调用构造方法")

    def __init__(self, name):
        self.name = name
        print("self = ", self)
        print("self.__class__", self.__class__)

    def m1(self):
        return 'hello class'


# 实例化类
clazz = MyClass("赵子龙")

# 访问类的属性和方法
print("属性 i 为:", clazz.name)
print("调用 m1方法,输出为:", clazz.m1())

在这里插入图片描述

3.2 给类对象动态添加/删除变量

Python 支持为已创建好的对象动态增加/删除实例变量。

  • 动态增加:通过直接增加一个新的实例变量并为其赋值即可。
  • 动态删除:使用 del 语句即可实现

示例代码如下:

obj = MyClass("赵子龙")

# 动态增加实例变量
obj.age = 18
print("动态增加变量:age = ", obj.age)

# 动态删除实例变量
del obj.age
# 访问不存在的变量,此时会报错
print(obj.age)

在这里插入图片描述

3.3 给类对象动态添加方法

Python 也允许为对象动态增加方法。

注意:为类对象动态增加的方法时,Python 不会自动将调用者自动绑定到第一个参数(即使将第一个参数命名为 self 也没用),因此程序必须手动为第一个参数传入参数值。

示例代码如下:

obj = MyClass("赵子龙")

# 先定义一个函数
def fun1(self, desc):
    print("---fun1函数---  self = ", self)
    print("---fun1函数---  desc = ", desc)

# 动态绑定方法
obj.m2 = fun1

# 手动将调用者绑定为第一个参数
obj.m2(obj, "动态绑定方法 fun1")

在这里插入图片描述
如果不想手动给 动态增加方法 进行 self 传值时,通过借助 types 模块下的 MethodType 可以实现。

示例代码如下:

obj = MyClass("赵子龙")

# 先定义一个函数
def fun1(self, desc):
    print("---fun1函数---  self = ", self)
    print("---fun1函数---  desc = ", desc)

# 导入MethodType
from types import MethodType
obj.m2 = MethodType(fun1, obj)

# 调用方法,第一个参数不用传
obj.m2("动态绑定方法 fun1")

三、类属性

1、类变量

在类体中,所有函数之外定义的变量,称为类属性或类变量

其特点是,所有类的实例化对象都同时共享类变量,也就是说,类变量在所有实例化对象中是作为公用资源存在的。

类方法的调用方式有 2 种:

  • 可以使用类名直接调用,
  • 也可以使用类的实例化对象调用。

示例代码如下:

class MyClass:
    name = "赵云" # 类变量

    # 构造方法
    def __init__(self):
        print("调用构造方法")

    def m1(self):
        self.sex = "猛男" # 实例变量
        return 'hello class'

# 实例化类
obj = MyClass()

print("实例访问:name = ", obj.name)
print("类名访问:name = ", MyClass.name)

print("-------------")

#修改类变量的值
MyClass.name = "name修改啦"
print("实例访问:name = ", obj.name)
print("类名访问:name = ", MyClass.name)

在这里插入图片描述

注意:

  • 因为类变量为所有实例化对象共有,通过类名修改类变量的值,会影响所有的实例化对象。
  • 通过类对象是无法修改类变量的。通过类对象对类变量赋值,其本质将不再是修改类变量的值,而是在给该对象定义新的实例变量。

2、实例变量

在类体中,所有函数内部,以“self.变量名”的方式定义的变量,称为实例属性或实例变量。

其特点是,只作用于调用方法的对象。另外,实例变量只能通过对象名访问,无法通过类名访问。

示例代码如下:

# 实例化类
obj = MyClass()

print("调用 m1方法,输出为:", obj.m1())
print("类对象访问实例变量:sex = ", obj.sex)
print("类名访问实例变量:sex = ", MyClass.sex) # AttributeError: type object 'MyClass' has no attribute 'sex'

3、局部变量

在类体中,所有函数内部里面以“变量名=变量值”的方式定义的变量,称为局部变量。

class MyClass:

    def m1(self):
        self.sex = "猛男" # 实例变量
        say = self.sex * 3 # 局部变量
        desc = "简介" # 局部变量
        print("打印:desc={}, say={}".format(desc, say))
        return 'hello class'

# 实例化类
obj = MyClass()

print("调用 m1方法,输出为:", obj.m1())

在这里插入图片描述

4、私有属性

__private_attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs

class JustCounter:
    __secretCount = 0  # 私有变量
    publicCount = 0    # 公开变量
 
    def count(self):
        self.__secretCount += 1
        self.publicCount += 1
        print (self.__secretCount)
 
counter = JustCounter()
counter.count()
counter.count()
print (counter.publicCount)
print (counter.__secretCount)  # 报错,实例不能访问私有变量

四、方法

1、类实例方法

不用任何修改的方法为实例方法。

实例方法最大的特点就是,它最少也要包含一个 self 参数,用于绑定调用此方法的实例对象(Python 会自动完成绑定)。

  • 使用类对象直接调用实例方法,无需手动给 self 参数传值(推荐使用)。
  • 使用类名调用实例方法,需要手动给 self 参数传值。

用类的实例对象访问类成员的方式称为绑定方法,而用类名调用类成员的方式称为非绑定方法。

示例代码如下:

class MyClass:

    def m1(self):
        return 'hello class'

# 实例化类
obj = MyClass()

print("类对象调用实例方法,输出为:", obj.m1())
print("类名调用实例方法,输出为:", MyClass.m1(obj))

2、类方法

采用 @classmethod 修饰的方法为类方法。

类方法,它最少也要包含一个参数,只不过类方法中通常将其命名为 cls(cls 参数的命名也不是 Python规定的,只是程序员约定俗称的习惯),Python 会自动将类本身绑定给 cls 参数(注意,绑定的不是类对象)。我们在调用类方法时,无需显式为 cls 参数传参。

类方法推荐使用类名直接调用,当然也可以使用实例对象来调用(不推荐)。

示例代码如下:

class MyClass:

    @classmethod
    def mm2(cls):
        return 'this is 类方法'

# 使用类名直接调用
print(MyClass.mm2())

#使用类对象调用
obj = MyClass()
print(obj.mm2())

3、类静态方法

采用 @staticmethod 修饰的方法为静态方法。

静态方法和函数唯一的区别是,静态方法定义在类这个空间(类命名空间)中,而函数则定义在程序所在的空间(全局命名空间)中。

静态方法没有类似 self、cls 这样的特殊参数,因此 Python 解释器不会对它包含的参数做任何类或对象的绑定。也正因为如此,类的静态方法中无法调用任何类属性和类方法。

示例代码如下:

class MyClass:

    @staticmethod
    def sum(x, y):
        return x + y

# 使用类名直接调用
print(MyClass.sum(2,3))

# 使用类对象调用
obj = MyClass()
print(obj.sum(5,4))

4、私有方法

__private_method:两个下划线开头,声明该方法为私有方法,只能在类的内部调用 ,不能在类的外部调用。self.__private_methods

class Site:
    def __init__(self, name, url):
        self.name = name   # public
        self.__url = url   # private
 
    def who(self):
        print('name  : ', self.name)
        print('url : ', self.__url)
 
    def __foo(self):          # 私有方法
        print('这是私有方法')
 
    def foo(self):            # 公共方法
        print('这是公共方法')
        self.__foo()
 
x = Site('百度一下', 'www.baidu.com')
x.who()        # 正常输出
x.foo()        # 正常输出
x.__foo()      # 报错

Python中有关 描述符和 property()函数可以自行了解一下,都是一种对类中属性的访问方式。

– 求知若饥,虚心若愚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值