一、面向对象基本语法

1、面向对象的核心思想
在这里插入图片描述
2、面向对象基本语法
创建类和对象:
创建类:class 类名, 类名要用驼峰式(单词首字母大写)
创建对象:类名()

# 创建类
class Car:
    print('我是造车图纸')

# 创建对象
target = Car()     # 创建对象的时候会自动执行类里面的内容
-------------------------------------
我是造车图纸

类中有两样内容
属性:用来初始化一个对象
动作:用来创建一个对象所拥有的功能,常被写成函数(类中的函数被称作方法)

# 创建类,类名:Car
class Car:
    # 创建属性__init__(self),用来初始化这个对象:通过self来初始化对象中的变量,self相当于js/php中的this
    def __init__(self, color, name):   # color,type就是对象中的变量
        print('我是属性')
        # self给车添加属性
        self.color = color             # 被初始化的变量就叫做实例变量,比如:self.color
        self.type = name
        slef.age  = 23                 # 可以自定义一个初始化变量

    # 创建动作(方法),用来描述对象所拥有的功能
    def run(self):
        print('我能跑')

# 创建对象,把参数传给属性        
target = Car('红色','奔驰')

访问类中的方法
self.方法(self就是target)

# 创建类,类名:Car
class Car:
    # 创建属性__init__(self),用来初始化这个对象:通过self来初始化对象中的变量
    def __init__(self, color, name):   # color,type就是对象中的变量
        print('我是属性')
        print('self对象的ID:',self)
        # self给车添加属性
        self.color = color             # 被初始化的变量就叫做实例变量,比如:self.color
        self.type = name

    # 创建动作(方法),用来描述对象所拥有的功能
    def run(self):
        print('我能跑')

# 创建对象target,对象负责把值传给属性__init__并进行初始化,属性中的self就是target对象,它们的id一样
target = Car('红色','奔驰')
print('terget对象的ID:',target)

# 使用对象访问类中的方法
target.run()
-------------------------------
我是属性                       # 默认会执行属性__init__(self)里面的内容
self对象的ID:   <__main__.Car object at 0x0000012DF92C4828>  # 说明self就是target
terget对象的ID: <__main__.Car object at 0x0000012DF92C4828>
我能跑                         # 调用类中的方法

3、造对象的过程(原理)
我们创建类的时候,默认生成一个__new__,但是不显示
当我们使用Foo() 去创建一个对象的时候,会优先执行__new__,并在__new__里面开辟一块内存(相当于开了一块地),然后__init__在这个内存地址里面进行初始化对象的操作。
在这里插入图片描述

二、成员与类变量

1、成员与类变量
实例变量:被对象初始化过的变量,通过对象调用:【对象.变量】
类变量:在类中定义的变量,作用于整个类,通过类名调用:【类名.变量】

class Car:
    age = 23                          # 类变量,作用于整个类中
    def __init__(self, color, name):
        self.color = color            # 实例变量,被初始化的变量,比如:self.color
        self.type = name

    def run(self):
        print('我能跑')

# 创建对象
target = Car('红色','奔驰')
print(target.color)  # 通过对象去访问实例变量,就相当于self.color
print(Car.age)       # 通过类名访问类变量
--------------------------------------------
红色
23

三、方法

一、方法,其实就是类中的函数。
1、实例方法
通过对象调用,【对象.方法】

哪个对象调用这个方法,self就是那个对象

class Car:
    age = 23
    def __init__(self, color, name):
        self.color = color
        self.type = name

    # 创建实例方法
    def run(self):
        # 通过对象调用实例变量,通过类名调用类变量
        print(f'我叫{self.type},我今年{Car.age}岁了,我是{self.color}的')

# 创建对象
target = Car('红色','奔驰')
# 调用实例方法 [对象.方法]
target.run() 
-------------------------------------
我叫奔驰,我今年23岁了,我是红色的

1.1 验证这句话【哪个对象正在调用这个方法,self就是那个对象】

class Func:

    def fangfa(self):
        print(self)    # 打印self

F = Func()             # 造对象
F.fangfa()             # 用对象访问方法
print(F)               # 打印对象 print(Func())
-------------------------------------------------
<__main__.Func object at 0x000001CE899452B0>        # 打印的self
<__main__.Func object at 0x000001CE899452B0>        # 打印的对象F

2、类方法
通过类名调用, 类名.方法
必须在上面加上一个@classmethod装饰器,第一个参数是cls,cls接收一个类名(cls==类名)
一般用来创建对象: cls() == 类名()
哪个类名正在调用这个类方法,cls就是那个类名

class Car:
    age = 23
    def __init__(self, color, name):
        self.color = color
        self.type = name

    # 创建实例方法
    @classmethod
    def run(cls,var1,var2):   # 里面可以带参数
        print(f'我是类方法{var1}{var2}')
        print('打印cls:',cls)

# 调用类方法 [类名.方法]
Car.run('哈哈','呵呵')
print('打印类名:',Car)       # 类名ID与clsID一样,所以类名==cls
-------------------------------------------------
我是类方法哈哈呵呵
打印cls: <class '__main__.Car'>
打印类名: <class '__main__.Car'>

2.1 验证这句话[哪个类名正在调用这个类方法,cls就是那个类名]

class Func:
    @classmethod
    def lei(cls):
        print(cls)     #打印cls

Func.lei()        # 调用类方法
print(Func)       # 打印类名
-----------------------------------
<class '__main__.Func'>  # 打印cls
<class '__main__.Func'>  # 打印类名

2.2、类方法使用例子

# 创建类
class User:
    # 初始化对象
    def __init__(self, username, password):
        self.username = username
        self.password = password

    #  实例方法
    def names(self):
        print(f'my name is {self.username}')

    # 类方法
    @classmethod
    def login(cls):
        while 1:
            username = input('请输入用户名:').strip()
            password = input('请输入密码').strip()
            if username == 'alex' and password == '123456':
                return cls(username, password)  # 创建对象,cls就是类名(相当于User(username,password)
            else:
                print('用户名或密码错误')


u = User.login()  # 通过执行类方法来创建对象,User.login()返回值是 cls(username,password)==User(username,password)
u.names()         # 通过对象调用实例方法
---------------------------------------------
请输入用户名:alex
请输入密码123456
my name is alex

3、静态方法
通过类名调用
就是在类里面写的一个函数,必须在上方加上一个@staticmethod装饰器,参数无要求
一般用于做一些算数逻辑

class Car:
    age = 23
    def __init__(self, color, name):
        self.color = color
        self.type = name

    # 创建实例方法
    @staticmethod
    def run(var):   # 里面可以带参数
        print(f'我是静态方法{var}')

# 调用静态方法 [类名.方法]
Car.run('haha')
----------------------------------------
我是静态方法haha

4、属性方法
本质:把属性方法的返回值变成一个实例变量
访问的时候是通过 【对象.方法】访问就像是在访问实例变量,而不是【对象.方法()】
用途:实时计算一个东西

from datetime import datetime
class Person:
    # 类变量,获取今年年份
    times = int(datetime.now().strftime("%Y"))
    def __init__(self, birth_year):
        self.birth_year = birth_year
        # self.age = Person.times - self.birth_year  #本来应该是这样去计算年龄的

    # 属性方法,可以实时去计算年龄
    @property  # 负责把一个方法改成实例变量,把这个方法的返回值变成了self.age
    def age(self):
        print('你今年的年龄是:')
        return  Person.times - self.birth_year  # 类变量-实例变量


year = int(input('请输入你的出生年份:'))
p = Person(year)       # 造对象
print(p.age)           # 调用属性方法,注意方法名不加括号(就相当于在调用 self.age)
---------------------------------------
请输入你的出生年份:1991
你今年的年龄是:
28

4.1、给属性方法重新赋值

class Person:
    def __init__(self,money):
        self.money = money
        #print(self.money)

    # 属性方法
    @property
    def prize(self):
        return '本次累计奖金是:', 20000 + self.money

    # 属性方法的分身
    @prize.setter  # 修改上一个方法的返回值,把一个新的值带进去重新计算
    def prize(self, var1):
        self.var1 = var1    # self.var1 把新的变量初始化成实例变量
        print('下次累计奖金是', 20000 + self.var1)
        self.money = 20000 + self.var1   # 还可以把改变的结果重新赋值给实例变量

p = Person(500)    # 创建对象
print(p.prize)     # 打印第一个prize的返回值
p.prize = 1000     # 我对第一个prize返回值不满意,所以通过@prize.setter给var1传入一个新的值,去改变prize的结果,再次打印新的prize的返回值
----------------------------------------------
('本次累计奖金是:', 20500)
下次累计奖金是 21000

5、在一个类中调用另一个类中的变量

# 在Person类中调用Func类中的name
class Func:
    def __init__(self, name):
        self.name = name

class Person:
    def __init__(self,age):
        self.age = age        # self.age 就等于对象 Func('alex')
        
    def test(self):
        print(self.age.name)  # 在Person类中调用Func类中的name, 就等于执行 Func('alex').name

F = Func('alex')    # 造对象,把'alex'给变量name
P = Person(F)        # 造对象,把Func('alex')这个对象给变量age
-----------------------------------------
alex

6、在一个方法中调用另一个方法中的变量
如果一个类下面的函数都需要去执行某个变量,要么把这个变量写成全局变量,通过global去调用,要么放到init里面,要么就使用下面的方法把这个函数专门当成变量函数
函数里面的变量只能作用于当前函数中使用,别的函数不能去调用
一个函数最好只办一件事,不用把所有功能都写到一个函数中,不然会出问题的。

(1) 写法一
class Func:
    # 这个函数专门是用来获取age的,里面不要放其他代码
    def test1(self):
        age = input('请输入年龄:')   # 定义全局变量,这个变量无法在外面访问
        self.age = age              # 只能先把全局变量转换成实例变量

    def test2(self):
        # self.test1()              # 在这里先执行一个test1也可以
        print(self.age)           # 这边才能够拿到self.age

F = Func()  # 造对象
F.test1()   # 必须先执行一次test1
F.test2()
---------------------------------------
请输入年龄:23
23

(2)写法二
class Func:
    # 这个函数专门是用来获取age的,里面不要放其他代码
    def test1(self):
        age = input('请输入年龄:')   # 定义全局变量,这个变量无法在外面访问
        self.age = age              # 只能先把全局变量转换成实例变量
        return self.age             # 作为return返回值

    def test2(self):
        print(self.test1())        # 执行test1()并打印return返回值

F = Func()  # 造对象
F.test2()
-----------------------------------
请输入年龄:23
23


(3)写法三
class Func:
    def test1(self):
        self.name = 'alex'
        self.test2()            # 先执行一遍test2()

    def test2(self):
        print('哈哈',self.name)  # 可以直接使用test1()里面的变量

F = Func()
F.test1()     # 调用test1()方法
----------------------------------
哈哈 alex

7、在一个类的方法中调用另一个类中的方法中的变量

class Func:
    # 实例方法
    def test(self):
        self.age = 111

class Func2(Func):     # 继承
    def test2(self):
        self.test()      # 先把test()方法引用进来
        print(self.age)  # 再去打印test()中的变量

F = Func2()    # 创建Func2()的对象
F.test2()      # 执行test2()方法

四、私有

1、私有
__开头的内容都是私有
私有内容只能在类里面访问,不允许在类外面访问

class Person:
    __names = 'Alex'             # 私有类变量
    def __init__(self,name,age):
        self.__name = name        # 初始化成私有实例变量
        self.__age = age

    def discrib(self):
        print('my name is %s' %(self.__name))       # 私有实例变量只能通过%s使用
        print(f'My NAME Is {self.__name}')          # 私有实例变量也可以这么用(pycharm会提示,不用管它)
        print(f'my name is %s' %(Person.__names))   # 私有实例变量不能这么用

p = Person('oldboy','23')
p.discrib()
print(p__name)    # 这样是不行的
----------------------------------
my name is oldboy
My NAME Is oldboy
my name is Alex

五、特殊成员

1、这里只是稍微简单介绍一下,一般很少能用到
特殊成员只有在特殊情况下才会被访问. 一般我们很少主动去访问这些内容. 都是自动调用的.
比如, 我们在创建对象的时候, 会默认执行__init__()方法
init: 创建对象的时候执行__init__
new: 创建对象的时候执行__new__
call: 当执行 对象() 的时候执行__call__

特殊成员只有在特殊情况下才会被访问. 一般我们很少主动去访问这些内容. 都是自动调用的.
比如, 我们在创建对象的时候, 会默认执行__init__()方法

class Foo:
    def __init__(self):
        print('默认也会访问我')

    def __new__(cls,*args, **kwargs):
        print('默认先会访问我')
        return super().__new__(cls)

    def __call__(self, *args, **kwargs):
        print('默认最后访问我')

f = Foo()   # 创建对象时,默认会先执行__new__,后执行__init__
print('---------------')
f()   # 把对象当成函数一样去执行,默认会执行到__call__

getitem
settiem
delitem

class Foo:
    def __init__(self):
        self.dic = {}     # 创建一个空字典

    # 用于添加
    def __setitem__(self, key, value):
        print('我是setitem')
        print(key, value)
        self.dic[key] = value  # 调用实例变量,把用户输入的key value 写入字典中

    # 用于查询
    def __getitem__(self, item):
        print('我是getitem')
        return self.dic.get(item)  # 调用实例变量,去字典中查询item对应的值

    # 用于删除
    def __delitem__(self, key):
        print('我是delitem')
        self.dic.pop(key)     # 调用实例变量,删除字典中的key

f = Foo()        # 创建对象
f["name"] = "alex"  # 调用__setitem__方法,把"name"给key,把"alex"传给value,并写入字典
print(f["name"])     # 调用__getitem__方法, 把"name" 传给item,并进行查询
del f['name']       # 调用__delitem__方法删除字典里面的key
print(f.dic)         # 查看字典中的内容
----------------------------------------------
我是setitem
name alex
我是getitem
alex
我是delitem
{}

六、继承

一、继承
作用:减少代码量,让父类作为公共代码供子类调用

1、单继承
子类可以继承父类中私有内容 (__开头的) 以外的所有内容

class Animal:                   # 父类
    def cry(self):
        print('我会汪汪叫')

class Cat(Animal):              # 子类继承父类,子类是Cat, 父类是Animal
    def catch_mouse(self):
        print('我会抓老鼠')

p = Cat()  # 创建子类的对象
p.catch_mouse()
p.cry()    # 由于子类继承了父类,所以子类对象也可以调用父类里面的方法
----------------------------------------------
我会抓老鼠
我会汪汪叫

子类中可以有和父类重名的方法,优先会执行子类中的方法

class Animal:                   # 父类
    def cry(self):
        print('我会汪汪叫')

    def like(self):
        print('我最爱吃肉骨头')

class Cat(Animal):              # 子类继承父类,子类是Cat, 父类是Animal
    def catch_mouse(self):
        print('我会抓老鼠')

    def cry(self):
        print('我会喵喵叫')

p = Cat()  # 创建子类的对象
p.catch_mouse()
p.cry()    # 如果子类里面的方法和父类里面的方法重名,优先执行子类里面的方法
p.like()
---------------------------------
我会抓老鼠
我会喵喵叫
我最爱吃肉骨头

2、多继承

class Father1:                        # 父类1
    def apple(self):
        print('Father1可以给你买苹果')

    def play(self):
        print('Father1可以陪你玩')

    def car(self):
        print('Father1开法拉利陪你玩')

class Father2:                        # 父类2
    def orange(self):
        print('Father2可以给你买橘子')

    def play(self):
        print('Father2可以陪你玩')

    def car(self):
        print('Father2开凯迪拉克陪你玩')

class Son(Father1, Father2):    # 子类继承2个父类,执行顺序:就近原则
    def play(self):
        print('自己和自己玩')

p = Son()     # 造子类对象

p.apple()     # 由于子类继承了父类,所以子类对象可以调用父类中的方法
p.orange()

p.play()      # 出现同名方法,优先执行子类中的方法
p.car()       # 父类中出现同名方法,优先执行最近的父类中的方法
--------------------------------
Father1可以给你买苹果
Father2可以给你买橘子
自己和自己玩
Father1开法拉利陪你玩

3、super()
如果子类/父类中的方法执行完,还想继续执行下一个类中的方法就用super()

class Father1:
    def play1(self):
        print('Father1开飞机陪你玩')

    def money(self):
        print('Father1每天给10000块钱')

class Father2:
    def play2(self):
        print('Father2开飞船陪你玩')

    def play1(self):
        print('Father2开飞碟陪你玩')

    def money(self):
        print('Father2每天给1块钱')
        super().money()   # 继续执行下一个类中的money()

class Son(Father2,Father1):  # 就近原则
    def like(self):
        print('哈哈哈')
        super().play2() # 执行完子类中的方法后继续执行下一个类中的play2()方法
        super().play1() # 执行完子类中的方法后继续执行下一个类中的play1()方法
        # super(Son, self).play1()  # 也可以写成这样,直接tab补全就行,意思是执行Son后面的类中的方法


p = Son()  # 造子类对象
p.like()   # 先找子类中的方法并执行
p.money()  # 如果子类中没有这个方法就执行父类中的方法,先去Father2中找
print(Son.mro())  # 如果继承关系很复杂可以通过mor() 查看优先执行顺序
----------------------------------------------------
哈哈哈
Father2开飞船陪你玩
Father2开飞碟陪你玩
Father2每天给1块钱
Father1每天给10000块钱
[<class '__main__.Son'>, <class '__main__.Father2'>, <class '__main__.Father1'>, <class 'object'>]

4、super()的继承原理

class Father:
    def __init__(self, address):  # (4) 这里的self == s对象,并初始化s对象中的address
        self.address = address

class Son(Father):
    def __init__(self, address):  # (2)初始化对象,self==s对象
        super(Son, self).__init__(address)   # (3)执行父类中的__init__,这里的self是子类中的self传过来的==s对象,并把address传给父类
        #super().__init__(address) # 或写成这样


s = Son('北京')  # (1)创建对象
print(s.address)
----------------------------------------------
北京

七、反射

一、反射(就是方便在某一个对象中去寻找某一个功能并执行)
getattr 可以从模块、类、对象中获取功能,在python中一切皆对象,所以说getattr可以从对象中获取功能
getattr(对象, 功能):在某一个模块中去寻找某个功能 (get表示找,attr表示功能)
hasattr(对象,功能):判断模块中是否有某个功能
callable() 判断某个功能能否被调用(只有函数、类、对象能被调用)

1、定义一个模块mode12.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# 这是创建的模块mode12

name = 'alex'

# 功能
def play():
    print('正在玩')

def run():
    print('正在跑')

def eat():
    print('正在吃')

2、getattr() 用法

import mode12                # 引入定义的模块
fn = getattr(mode12, "run")  # 在mode12模块中找run这个功能(注意用引号引起来),并赋值给fn
fn()                         # 找到后就去执行这个功能
-----------------------------------------------------
正在跑

3、hasattr() 用法

(1) 如果mode12模块中有run功能,则返回True,否则返回False
import mode12
print(hasattr(mode12, "run"))
------------------------------
True

(2) hasattr 结合 getattr 使用
import mode12
if hasattr(mode12, "run"):       # 判断mode12模块中是否有这个功能
    fn = getattr(mode12, "run")  # 如果有这个功能,就获取这个功能
    fn()                          # 并执行这个功能
else:
    print('没有找到这个功能')

4、callable()用法

import mode12
gn = input('请输入查找的功能:')
# 判断mode12模块中是否有这个功能,这里的功能需要用""引起来
if hasattr(mode12, gn):
    # 如果有这个功能,就获取这个功能
    fn = getattr(mode12, gn)
    # 判断这个功能是否能被调用(函数、类、对象都可以被调用)
    if callable(fn):
        fn()                          # 能被调用就执行这个功能
    else:
        print(fn)                     # 不能被调用就打印这个功能(比如变量)
else:
    print('没有找到这个功能')
------------------------------------
请输入查找的功能:run
正在跑

5、用getattr() 从类中获取功能

class Func:
    name = 'alex'
    # 功能
    def play(self):
        print('正在玩')

    @classmethod
    def run(cls):
        print('正在跑')

# 调用类里面的实例方法
fn = getattr(Func, 'play')
print(hasattr(Func, 'play'))
fn('')         # 里面必须加点东西

# 调用类里面的类方法
fc = getattr(Func, 'run')
fc()         # 里面不用加东西
---------------------------------------
True
正在玩
正在跑

6、用getarrt() 从对象中获取内容

class Func:
    name = 'alex'
    # 功能
    def play(self):
        print('正在玩')

    @classmethod
    def run(cls):
        print('正在跑')

# 造对象
F = Func()

# 从对象中获取实例方法
print(hasattr(F, 'play'))
fn = getattr(F, 'play')
fn()      # 这里相当于F.play()

# 从对象中获取类方法
fn = getattr(F, 'run')
fn()      # 这里相当于F.run()

# 给对象创建一个新的变量,内容是'girl' (创建在内存里面)
setattr(F, 'hobby', 'girl')           # setattr(对象,方法, 内容),用的少
print(F.hobby)
--------------------------------------
True
正在玩
正在跑
girl

八、约束

一、约束
子类继承父类后,必须让子类重新某个方法
1、原理

class Father:
    def sleep(self):
        raise NotImplementedError('你需要自己创建这个方法')

class Son(Father):      # 子类继承父类
    pass

# 如果子类想调用父类中的sleep()方法,就会报错,必须自己去创建sleep()方法
S = Son()
S.sleep()   
------------------------------
NotImplementedError: 你需要自己创建这个方法

九、三元表达式

1、三元表达式
条件成立返回a,否则返回b

# 返回最大的值
a = 1
b = 2
c = a if a>b else b  # 如果a>b就返回a,否则返回b
print(c)
-----------------------------
2
Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐