python学习日记10 python基本语法(面向对象&类和对象&类中的成员&对象属性的动态绑定)

这篇博客主要介绍了Python中的面向对象编程,包括类和对象的概念,类的定义和对象的创建,成员函数的定义和访问,动态绑定属性,构造函数,类属性和实例属性,以及内存中的对象行为。内容深入浅出,适合初学者了解Python的面向对象特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、面向对象

面向对象是基于万物皆对象这个哲学观点。在Python中,一切皆对象

面向对象只是一种思想,并不是一门编程语言,也不会绑定编程语言

面向过程和面向对象的优缺点

面向过程

优点:性能比面向对象高,比如单片机、嵌入式开发等一般采用面向过程开发,因为性能是最重要的因素

缺点:没有面向对象易维护,易复用,易扩展,开销比较大,比较消耗资源

面向对象

优点:易维护,易复用,易扩展【由于面向对象有封装,继承,多态的特性,可以设计出低耦合的系统,使
得系统更加灵活,更加易于维护】

缺点:性能比面向过程低

1.类和对象

1.1 概念

:一个具有特殊功能的实体的集合【群体】,是抽象的

对象:在一个类中,一个具有特殊功能的实体,能够帮忙解决特定的问题【对象也被称为实例】,是具体的

两者之间的关系:类用于描述某一类对象的共同特征,而对象则是类的具体存在

1.2 类的定义和对象的创建

格式:

class  类名():
	类体

说明:

​ a.Python中使用class关键字定义类

​ b.类名只要是一个合法的标识符即可,但是要求:遵循大驼峰命名法 ,如:KeyError,ValueError,NameError,IndexError…….

​ c.尽量使用单个或多个有意义的单词连接而成

​ d.通过缩进来体现类体的存在

​ e.类体一般包含两部分内容:对类的特征描述和行为描述

# 一、类的定义
# 1.基本语法
# a.函数
# 函数的声明和实现
def func():
    print("ok")     # 函数体
print(func)         # 函数本身:<function func at 0x102587f70>
func()              # 调用函数:执行函数

# b.类
# 类的声明和实现
class Func():
    pass     # 类体
print(Func)  # 自定义类:<class '__main__.Func'>
Func()       # 创建对象

"""
注意:
    a.同一个py文件中可以定义多个类,但是,在实际项目开发中,如果需求较为复杂,类的定义建议一个py文件定义一个类
    b.当一个函数定义完毕,则需要手动调用,否则无法执行
      当一个类定义完毕,当类被加载的时候,其中的类体也会被加载
"""

# 二、创建对象/类的实例化
# 语法:对象名  = 类名(....),目前为空
mc1 = MyClass1()
print(mc1)  # <__main__.MyClass1 object at 0x10726bdc0>
print(type(mc1))  # <class '__main__.MyClass1'>

"""
注意:
    a.创建对象的过程,本质上就是定义变量的过程,该变量中存储的是创建出来的对象的地址
    b.打印对象的时候,默认的情况下,打印的是该对象在内存空间中的地址,
      但是,像int,str,list。。。常用的数据类型,系统已经处理过了,所以直接打印结果
    c.一个普通的类,可以创建无数个对象,每个对象在内存空间中拥有独立的地址
    d.对象名  = 类名(....)表示创建对象,但是该代码执行一次,则表示创建一个新的对象
"""

2.类中的成员/类体

2.1 成员函数的定义和访问

# 一、类中成员函数的定义
# 1.类的定义
class Person():
    # 2.多个对象共同的特征:变量

    # 3.多个对象共同的行为:函数
    """
    说明:
        a.self:自身,自己,在面向对象的函数中,self表示当前对象
        b.哪个对象调用函数,则该函数中的self表示就是哪个对象
        c.当调用函数的时候,self不需要手动传参,系统会自动完成传参,传递的是当前对象,只需要关注自定义的参数即可
        d.在Python中,self并不是一个关键字,只要是个合法的标识符即可,但是,为了表示当前对象,一般使用self
    """
    # 实例函数/对象函数,特点:第一个形参必须是self,只能由对象调用
    def run(self):
        print("running",id(self))
    def eat(self,sth):
        print("eating" + sth)

# 二、类中成员函数的访问
# 注意1:类和函数相似,会引入新的作用域,所以在类中定义的函数在类的外面无法直接调用
# 注意2:行为主要是由对象执行的,所以类中的函数需要调用,可以通过对象调用,语法:对象.函数(实参)
p1 = Person()
print("p1~~~~~~",id(p1))
p1.run()

2.2 动态绑定属性和限制绑定

# 类中多个对象共同的特征:变量,也被称为属性
# 通过动态绑定的属性被称为对象属性或实例属性

# 1.对象属性的动态绑定
# 语法:对象.属性 = 值
class Person():
    def show(self):
        print(f"姓名:{self.name},年龄:{self.age},身高:{self.height}")
# 创建对象
p1 = Person()
# 动态绑定属性
p1.name = '张三'
p1.age = 18
p1.height = 170
print(p1.name,p1.age,p1.height)
# 调用实例函数
p1.show()

p2 = Person()
# 注意1:给一个对象动态绑定的属性,另一个对象未绑定的情况下无法访问
# print(p2.name)  # AttributeError: 'Person' object has no attribute 'name'

# 注意2:不同的对象绑定了同名的属性,当一个对象的属性值发生改变时,对另一个对象的属性没有影响
print(p1.name,p2.name)
p1.name = 'jack.张'
print(p1.name,p2.name)

# 2.限制绑定对象的属性
class People():
    # 给系统属性__slots__定义一个元组,元组的元素就是允许绑定的属性字段名称
    # 注意1:为了限制当前类创建的对象只能绑定指定的属性
    # 注意2:如果只需要限制一个属性,则书写元素的时候,注意添加逗号,如: __slots__ = ("name",)
    __slots__ = ("name", 'age', 'height')
    def show(self):
        print(f"姓名:{self.name},年龄:{self.age},身高:{self.height}")

p2 = People()
p2.name = '李四'
p2.age = 10
p2.height = 180
# p2.hobby = 'dance'  # AttributeError: 'People' object has no attribute 'hobby'
p2.show()

3.构造函数

"""
	先创建对象,然后使用直接赋值【动态绑定属性】方式给对象绑定属性,可以使用,但是代码比较繁杂,一般情况下,很多类倾向于将对象创建为有初始状态的,常规用法中,在类中可以定义一个函数,名称为__init__,该特殊的函数被称为构造函数,主要用于给对象的数据做出初始化

强调:构造函数包括__new__和__init__

注意:在Python中,以__xxx__方式命名的函数被称为魔术函数/魔术方法,这类函数在使用的时候无需手动调用,在进
     行某个操作的时候会自动调用

构造函数,也被称为构造器,指的是当创建对象的时候,被自动调用的函数
"""
语法:
def __new__(cls,*args,**kwrags):
	pass
def __init__(self):
    pass
*******************************
class Person1():
    __slots__ = ('name','age','address')
    def __init__(self,name,age):
        print("init被调用了~~~~~",id(self),name,age)
        # 动态绑定属性
        self.name = name
        self.age = age
        self.address = '北京'   # 默认值
    def show(self):
        print(f"姓名:{self.name},年龄:{self.age}")
p1 = Person1('张三',10)
# print(id(p1))
print(p1.name,p1.age)
p1.show()
"""
总结:
    a.p1 = Person1()表示创建对象,当创建对象的时候,会自动调用__init__,__init__中的self表示当前对象
    b.如果需要给对象动态绑定属性,为了代码的可读性和后期的可维护性,一般将动态属性的绑定书写在__init__中
    c.在__init__中动态绑定属性,如果需要创建对象的时候传参,则设置形参,如果不需要传参,则可以直接定义
    d.当给__init__设置了和属性相关的参数之后,当创建对象的时候,一定要注意参数的匹配
     例如:p1 = Person1('张三',10)
          def __init__(self,name,age)
          将'张三'和10会自动传参给name和age
"""
# 构造函数的工作原理
class Animal():
    __slots__ = ('name','age')
    def __new__(cls, *args, **kwargs):
        print("new~~~~~~~")
        # super().__new__(cls)表示创建对象
        return super().__new__(cls)
    def __init__(self,name,age):
        print("init~~~",id(self))
        self.name = name
        self.age = age

a = Animal("大黄",4)
print(a)   # <__main__.Animal object at 0x1043e6cd0>
print(id(a))

"""
总结:
    a.真正意义上,构造函数包含__new__和__init__
    b.在实际开发中,常用__init__,因为__new__在类中没有定义,当创建对象的时候仍然会自动调用
    c.__new__:表示创建对象,该函数的返回值就是创建出来的对象
        例如:a = Animal("大黄",4),a指向__new__的返回值
      __init__:表示初始化对象,系统会自动将__new__的返回值【创建的对象】会自动传参给__init__中的self,
               同时,将需要初始化的值传参给__init__中的其他参数,完成对象初始化的过程
    d.构造函数中,当创建对象的时候,都是先调用__new__,然后才调用__init__
"""

4.类属性和实例属性

"""
类属性【类的字段】和实例属性【对象属性,对象的字段】的区别
1.定义位置不同:类属性直接定义在类中,实例属性定义在__init__中或在类的外面直接动态绑定定义
2.访问方式不同:类属性可以通过类名或对象访问,而实例属性只能通过对象访问
3.访问优先级不同:当类属性和实例属性重名时,通过对象访问,优先访问的是实例属性
4.在内存中出现的时机不同:类属性优先于实例属性出现在内存中,类属性随着类的加载而出现,实例属性是对象创建
  完毕之后才会出现
5.使用场景不同:类属性用于表示多个对象共享的数据,实例属性表示每个对象特有的数据
"""
# 1.定义位置:类属性直接定义在类中,实例属性定义在__init__中或在类的外面直接动态绑定定义
class Person():
    # 类属性:直接定义在类中
    num = 13
    data = "abc"
    def __init__(self,name,age):
        # 实例属性:给对象动态绑定
        self.name = name
        self.age = age
        self.num = 66
p = Person('jack',23)
# 实例属性:给对象动态绑定
p.hobby = 'dance'

# 2.访问方式:类属性可以通过类名或对象访问,而实例属性只能通过对象访问
# a.类属性
print(Person.num)
print(p.num)

# b.实例属性
print(p.name)

# 3.访问优先级不同:当类属性和实例属性重名时,通过对象访问,优先访问的是实例属性
print(p.num)     # 66
del p.num    # 因为优先访问实例属性,所以删除的是实例属性
print(p.num)    # 13

# 注意1:对象.属性 = 值,该语法都表示给当前对象动态绑定属性,或给指定对象修改实例属性,
# 哪怕类属性和实例属性同名,也表示实例属性
# p.data = 'hello'    # 并不是修改类属性,而是给p对象动态绑定了一个data实例属性
print(Person.data)   # abc
print(p.data)        # hello

# 注意2:如果需要修改类属性,则必须通过类名访问,语法:类名.类属性 = 值
Person.data = 'xyz'
print(Person.data)   # xyz
print(p.data)       # xyz

# 5.使用场景不同:类属性用于表示多个对象共享的数据,实例属性表示每个对象特有的数据
class Student():
    # 类属性
    school_name = '1000phone'
    def __init__(self,name,hobby):
        # 实例属性
        self.name = name
        self.hobby = hobby

5.内存中的对象

​ 不同对象访问同一个类属性,访问的是同一份内存空间,通过 类名.属性 = 值 修改类属性,一旦被修改所有对象访问到的结果都会随着修改

​ 不同对象的同名的实例属性,在内存中是不同的内存空间,一个发生修改,对另一个没有任何影响

6.析构函数

"""
析构函数__del__调用的时机:当对象被销毁的时候
"""
class Person():
    def __init__(self):
        print("构造函数被调用了")
    def __del__(self):
        print("析构函数被调用了~~~~~")

# 1.当对象被定义为全局变量,当程序结束之后,__del__会被自动调用
# print("start")
# p1 = Person()
# print("over")
"""
start
构造函数被调用了
over
析构函数被调用了~~~~~
"""

# 2.当对象被定义为局部变量,当函数调用完毕,__del__会被自动调用
# def func():
#     p1 = Person()
# print("start")
# func()
# print("over")
"""
start
构造函数被调用了
析构函数被调用了~~~~~
over
"""

# 3.当对象被del删除,则__del__会被自动调用
print("start")
p1 = Person()

del p1
print("over")
"""
start
构造函数被调用了
析构函数被调用了~~~~~
over
"""
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值