python的模块,面向对象,封装

"""
模块
# 一、模块导入
## 1. 定义
Python 模块(Module),是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句。
模块让你能够有逻辑地组织你的 Python 代码段。
把相关的代码分配到一个模块里能让你的代码更好用,更易懂。
模块能定义函数,类和变量,模块里也能包含可执行的代码。
包括:内置模块,自定义模块,第三方模块;

## 2. 作用
- 最大的好处是大大提高了代码的可维护性。其次,编写代码不必从零开始。
当一个模块编写完毕,就可以被其他地方引用。我们在编写程序的时候,也经常引用其他模块,
包括Python内置的模块和来自第三方的模块。

- 使用模块还可以避免函数名和变量名冲突。
相同名字的函数和变量完全可以分别存在不同的模块中,
因此,我们自己在编写模块时,不必考虑名字会与其他模块冲突。
但是也要注意,尽量不要与内置函数名字冲突。

## 3. 模块导入
### import
import导入模块执行的操作:
- 产生一个新的名称空间;
- 在新建的名称空间俩面执行模块(.py)的内容
- 拿到了一个模块名, 执行模块文件产生的名称空间.

### import .... as ...
对于导入的模块重命名

### from .... import ....
from .... import ..... as ....
从模块里面导入函数, 变量, 装饰器等.....

##4. 解决问题

问题: 导入模块时, 模块里面执行代码结果也会显示
解决方法:
    __name__, 所在文件没有当作模块导入是, 结果为__main__;
    __name__, 所在文件被当作模块导入是, 结果为模块的名称;


# 判断模块是否被导入, 如果没有被导入, 则执行下面的代码.
if __name__ == "__main__":
    print("这是写好的模块里面的显示.......")
    print(timeit(hello))
    print(__name__)

##5. __all__决定用来控制from xxx import *导入的内容


##6. 模块的分类
- 内置模块(random, string.....)
- 自定义模块(自己写的模块)
- 第三方模块(别人写好的模块)

## 7. 如何安装第三方模块
- pip3 install 模块名
导入模块练习
微信聊天机器人
import itchat
import requests

def get_tuling_reponse(_info):
    #print(_info)
    api_url = 'http://www.tuling123.com/openapi/api'
    data ={
        'key':'3526d29a41534231a58f7620dd4cad7c',
        'info':_info,
        'userid':'图灵机器人'
    }

    # 发送数据到指定网址,获取网址返回的数据
    res = requests.post(api_url,data).json()
    #print(res,type(res))
    # 给用户返回的内容
    print(res['text'])
    return res['text']

# get_tuling_reponse('给我讲个笑话~')
# get_tuling_reponse('给我讲个故事')
# get_tuling_reponse('cat')


# 时刻监控好友发送的文本消息,并且给予一个回复
# isGroupChat=True 接收群聊消息
# 注册响应事件,消息类型为itchat.content.TEXT,即文本消息
@itchat.msg_register(itchat.content.TEXT,isFriendChat=True)
def text_reply(msg):
    # 获取好友发送的文本消息
    # 返回同样的文本消息
    content = msg['Content']
    # 将好友的消息发送给机器人去处理,处理的结果就是返回给好友的消息
    returnContent = get_tuling_reponse(content)
    return returnContent

itchat.auto_login()
itchat.run()

在这里插入图片描述

import os
import itchat
# 在python中执行shell命令
# 1.第一种方式:可以判断命令是否执行成功;
# 返回值为0,执行成功
# 返回值不为0.执行是失败
# os.system('ls')
# res = os.system('hostnamess')
# print(res)

# 2.第二种方式 用来保存命令的执行结果的
# res = os.popen('hostname').read()
# print(res)


@itchat.msg_register(itchat.content.TEXT,isFriendChat=True)
def text_reply(msg):
    """
    需求:当我们的文件助手发送消息的时候,执发送的内容
        1.如果执行成功,显示执行结果
        2.如果执行失败,显示执行失败
    :param msg:
    :return:
    """
    if msg['ToUserName'] == 'filehelper':
        # 获取要执行的命令的内容
        command = msg['Content']
        # 让电脑执行命令代码
        # 如果执行成功,返回值是0
        if os.system(command) == 0:
            res = os.popen(command).read()
            result = '[返回值]-命令执行成功,执行结果:\n' + res
            itchat.send(result,'filehelper')
        # 如果命令执行失败
        else:
            result = '[返回值]-命令%s执行失败,请重试' %(command)
            itchat.send(result,'filehelper')

itchat.auto_login()
itchat.run()
import itchat
# 给指定好友发送消息

itchat.auto_login(hotReload=True)
# 根据好友昵称查找好友的信息,返回值是一个列表,有多个元素
res = itchat.search_friends('***')
#print(res)
# 通过索引获取该好友的详细信息
ly = res[0]['UserName']
while True:
    itchat.send('python',toUserName=ly)
面向过程:1--->2
--->3--->4 怎么做
面向对象:4 谁来做
    相对于函数来说是一个更大的封装,根据职责将对象所能实现的功能封装到一起
    1.确定对象要做的事情(方法->多个)
    2.让对象调用方法

植物大战僵尸
向日葵   豌豆射手      僵尸
生命值    生命值       生命值
生产阳光()  发射子弹()  移动()
摇摇晃晃()             咬()

类:是一群具有相同特征和行为事物的一个统称(抽象的-->不能直接使用)
        特征:被称为属性
        行为:被称为方法

对象:由类创建出来的一个具体的存在,由哪一个类创建出来的
对象,就拥有哪一个类中定义的方法和属性


先有类-->再有对象

类和对象的关系:
类是模板,对象是根据这个模板创建出来的,先有类再有对象
类只需要有一个,对象可以有很多个
不同对象(由同一类创建出来的对象)之间的属性可以不相同
类中定义了什么属性和方法,使用这个类创建出来的对象就有什么
属性和方法,不可能多也不可能少

类的设计
    1.类名:这类事物的名字(大驼峰命名法)
        大驼峰命名法
            1.每一个单词的首字母大写
            2.单词与单词之间没有下划线
    2.属性:这个类创建出来的对象有什么样的特征
    3.方法:这个类创建出来的对象有什么样的行为

类名的确定
名词提炼法分析整个业务流程,出现的名词,通常就是找到的类

属性和方法的确定
对 对象的特征描述,通常可以定义成属性
对象具有的行为(动词),通常可以定义为方法
提示:需求中没有涉及的属性或方法在设计类时,不需要考虑
例题演示
# 猫爱吃鱼,猫要喝水
# 哪一个对象调用的方法,self就是哪一个对象的引用
# 在类封装方法的内部,self就表示当前调用方法的对象自己
# 在的方法内部 可以通过 self.属性 来访问对象的属性
class Cat:
    def eat(self):
        print('%s 爱吃鱼' %(self.name))

    def drink(self):
        print('猫要喝水')

# 创建猫对象
tom = Cat()
# 在类的外部 对象.属性 可以给对象添加属性
# 不推荐使用
# 对象包含哪些方法,应该封装再类中
tom.name = 'Tom'
print(tom)
addr = id(tom)
print(addr)
# %x:打印格式为十六进制
print('%x' %(addr))
# %d:打印格式为十进制
print('%d' %(addr))
tom.eat()
tom.drink()

在这里插入图片描述

初始化方法
我们现在已经知道了使用 类名() 就可以创建一个对象
当使用类名()创建对象时,python的解释器会自动执行以下操作:
	1.为对象在内存中分配空间--创建对象
	2.调用初始化方法为对象的属性设置初始值--初始化方法(__init__)
这个初始化方法就是__init__方法,__init__是对象的内置方法
__init__方法是专门用来定义一个类具有哪些属性的方法


改造初始化方法--初始化的同时设置初始值:
在开发中,如果希望在创建对象的同时,就设置对象的属性,可以对__init__方法进行改造
1.把希望设置的属性值,定义成__init__方法的参数
2.在方法内部使用self.属性名 = 形参 接收外部传递的参数
3.在创建对象时,使用类名(属性1,属性2..)调用
"""
class Cat:
    def __init__(self,new_name):
        print('这是一个初始化方法')
        # self.属性名 = 属性的初始值
        #self.name = 'Tom'
        self.name = new_name
    # 在类中,任何方法都可以使用self.name
    def eat(self):
        print('%s 爱吃鱼' %(self.name))

# 使用类名()创建对象的时候,会自动调用初始化方法__init__
tom = Cat('tom')
# 定义属性之后,再用Cat创建对象的时候,都会拥有该属性
print(tom.name)
tom.eat()

lazy_cat = Cat('miaomiao')
print(lazy_cat.name)
lazy_cat.eat()

在这里插入图片描述

"""
__del__:对象被从内存中销毁前,会被自动调用

在python中
	当使用类名()创建对象时,为对象分配完空间后,自动调用__init__方法
	当一个对象被从内存中销毁前(把这个对象从内存中删除掉),
	会自动调用__del__方法

应用场景
__init__改造初始化方法,可以让创建对象更加灵活
__del__如果希望在对象被销毁前,再做一些事情,可以考虑一下__del__方法

生命周期(出生到死亡)
一个对象从调用类名()创建,生命周期开始
一个对象的__del__方法一但被调用,生命周期结束
在对象的生命周期内,可以访问对象属性,或者让对象调用方法
"""


class Cat:
    def __init__(self, new_name):
        self.name = new_name
        print('%s 来了' % (self.name))

    def __del__(self):
        print('%s 走了' % (self.name))


cat1 = Cat('tom')
print(cat1.name)
print('*' * 50)

cat2 = Cat('kimmy')
print(cat2.name)
# del关键字可以删除一个对象,del关键字自己调用__del__方法
del cat2
print('$' * 50)

在这里插入图片描述

"""
__str__:返回对象的描述信息 print函数输出使用

在python中,使用python输出对象变量,默认情况下,
会输出这个变量引用的对象是由哪>一个类创建的对象,
以及在内存中的地址(十六进制表示)
如果在开发中,希望使用print输出对象变量时,
能够打印自定义的内容,就可以利用__str__这个内置方法了
"""
class Cat:
    def __init__(self,new_name):
        self.name = new_name
    def __str__(self):
        # 必须返回一个字符串
        return '我是 %s' %(self.name)

cat = Cat('tom')
print(cat)
练习:
"""
栈的方法
    入栈 出栈 取栈顶元素
    栈的长度 判断栈是否为空
    显示栈的元素
"""
class Stack:
    def __init__(self):
        self.stack=[]

    def push(self,value):
        self.stack.append(value)
        return True
    def pop(self):
        if self.stack:
            # 获取出栈元素,并返回
            item = self.stack.pop()
            return item
        else:
            return False

    def top(self):
        if self.stack:
            return self.stack[-1]
        else:
            return False

    def length(self):
        return len(self.stack)

    def isempty(self):
        return self.stack == []

    def view(self):
        return ','.join(self.stack)

s = Stack()
print(s.push('1'))
s.push('2')
print(s.view())
item = s.pop()
print(item)
print(s.view())
print(s.isempty())
print(s.length())

在这里插入图片描述

"""
封装
1.封装是面向对象编程的一大特点
2.面向对象编程的第一步 将属性和方法封装到一个抽象的类中(为什么说是抽象的,因为类不能直接使用)
3.外界使用类创建对象,然后让对象调用方法
4.对象方法的细节都被封装在类的内部
"""
需求1:
1.小明和小美都爱跑步
2.小美体重45.0公斤
3.小明体重75.0公斤
4.每次跑步都会减少0.5公斤
5.每次吃东西都会增加1公斤

class person:
    def __init__(self, new_name, new_weight):
        self.name = new_name
        self.weight = new_weight
        print('%s爱跑步,现在%s公斤' % (self.name, self.weight))
# 在对象方法内部,可以直接访问对象的属性
    def run(self):
        self.weight -= 0.5
        print('%s跑了一次步,还剩%s公斤' % (self.name, self.weight))

    def eat(self):
        self.weight += 1
        print('%s吃了一次东西,还剩%s公斤' % (self.name, self.weight))

# 同一个类创建出多个对象之间,属性互补干扰的
a = person('小明', 75)
b = person('小美', 45)

a.eat()
b.run()
a.eat()
a.run()
b.eat()

在这里插入图片描述

需求2:摆放家具
1.房子有户型,总面积和家具名称列表
	新房子没有任何的家具
2.家具有名字和战地面积,其中
	床:占4平米
	衣柜:占2平面
	餐桌:占1.5平米
3.将以上三件家具添加到房子中
4.打印房子时,要求输出:户型,总面积,剩余面积,家具名称列表

两个类
家具类
房子类
因为房子类要使用家具 被使用的类 应该先开发
class HouseItem:
    # 初始化方法
    def __init__(self, name, area):
        self.name = name
        self.area = area

    def __str__(self):
        return '[%s]占地%.2f平方米' % (self.name, self.area)


class House:
    def __init__(self, house_type, house_area):
        self.house_type = house_type
        self.house_area = house_area
        # 剩余面积
        self.free_area = house_area
        # 家具名称列表
        self.Item_list = []

    def __str__(self):
        return ('户型:%s\n总面积:%.2f平方米[剩余:%.2f平方米]\n家具:%s'
                % (self.house_type, self.house_area, self.free_area, str(self.Item_list)))

    def add_item(self, item):
        # 1.判断家具的面积
        if item.area > self.free_area:
            print('%s的面积太大了,无法添加' % (item.name))
            return
        # 2.将家具的名称添加到列表中
        self.Item_list.append(item.name)
        # 3.计算剩余面积
        self.free_area -= item.area


# 1.创建家具
bed = HouseItem('bed', 4)
print(bed)
chest = HouseItem('chest', 2)
table = HouseItem('table', 1.5)

# 2.创建房子对象
my_home = House('一室一厅', 40)
# 将家具添加到房子里
my_home.add_item(bed)
my_home.add_item(chest)
my_home.add_item(table)
print(my_home)

"""
小结:
	1.主程序只负责创建房子对象和家具对象
	2.让 房子 对象调用add_item 方法 将家具添加到房子中
	3.面积计算,剩余面积,家具列表 等处理都被封装到房子类的内部


    1.封装是面向对象编程的一大特点
	2.面向对象编程的第一步 -- 将 属性 和 方法 封装到一个抽象的类中
	3.外界使用 类 创建 对象,然后让对象调用方法
	4.对象方法的细节都被封装在类的内部
"""

在这里插入图片描述

演练重点:一个对象的属性可以是另外一个类创建的对象
示例:士兵射击
需求:
1.士兵瑞恩有一把AK47
2.士兵可以开火(士兵开火扣动的是扳机)
3.枪 能够 发射子弹(把子弹发射出去)
4.枪 能够 装填子弹 --增加子弹的数量

Soldier                Gun
-------                -----------
name                    model
gun                     bullet_count
-------------------------------------
__init__(self)          __init__(self)
fire(self)              add_bullet(self,count)
                        shoot(self)
"""

class Gun:
    def __init__(self,name):
         # 枪的型号
        self.name=name
        # 子弹的数量(调用增加子弹的方法来增加子弹数量)
        self.bullet_count=0
    def add_bullet(self,count):
        self.bullet_count+=count
    def fire_bullet(self):
        # 判断子弹数量
        if self.bullet_count==0:
            print('[%s] 没有子弹了...' %(self.name))
            return
         # 发射子弹 子弹数量变化
        self.bullet_count -= 1
        print('%s 响了,还剩%s颗子弹 ' %(self.name,self.bullet_count))

class Soldier:
    def __init__(self,name):
        self.name=name
        # 枪(新兵没有枪
        self.gun=None

    def fire(self):
        # 1.判断士兵是否有枪
        if self.gun==None:
            print('[%s]还没有枪..'%self.name)
            return
        print('go!go!go!!!')
        self.gun.add_bullet(10)
        print('%s加了10颗子弹'%self.name)
        self.gun.fire_bullet()
# 创建枪对象
ak=Gun('ak47')
# 创建士兵对象
tom=Soldier('Tom')
tom.fire()
# 通过主程序的赋值语句,士兵有枪了
tom.gun=ak
tom.fire()
tom.fire()

在这里插入图片描述

"""
面向对象三大特性
1.封装:根据职责将属性和方法封装到一个抽象的类中
2.继承:实现代码的重用,相同的代码不需要重复的写

单继承:
子类拥有父类的所有方法和属性(子类只需封装自己特有的方法)
"""
class Animal:
    def eat(self):
        print('吃')
    def drink(self):
        print('喝')
    def run(self):
        print('跑')
    def sleep(self):
        print('睡')

class Cat(Animal):
    def call(self):
        print('喵喵~')

class Hellokitty(Cat):
    def speak(self):
        print('我可以说日语~')

# 创建猫对象
# fentiao = Cat()
# fentiao.eat()
# fentiao.drink()
# fentiao.run()
# fentiao.sleep()
# fentiao.call()

hk = Hellokitty()
hk.speak()
# 子类可以继承父类的所有属性和方法
hk.call()

# 继承的传递性,子类拥有父类的父类的属性和方法
hk.eat()
hk.drink()
hk.run()
hk.sleep()

"""
专业术语:
Cat类是Animal类的子类,Animal类是Cat类的父类,Cat从Animal类继承
Cat类是Animal类的派生类,Animal类是Cat类的基类,Cat类从Animal类派生
"""
class Animal:
    def eat(self):
        print('吃')
    def drink(self):
        print('喝')
    def run(self):
        print('跑')
    def sleep(self):
        print('睡')

class Cat(Animal):
    def call(self):
        print('喵喵~')

class Hellokitty(Cat):
    def speak(self):
        print('我可以说日语~')
    def call1(self):
        super().call() # 只在python3中支持
        print('#@!#@!#@!')
    def call2(self):
        # 调用原本在父类中封装的方法
        Cat.call(self)
        print('1433223')
hk = Hellokitty()
hk.speak()
hk.call1()
hk.call2()

在这里插入图片描述

"""
多继承
子类拥有一个父类叫做单继承
子类可以拥有多个父类,并且具有所有父类的属性和方法
例如:孩子会继承自己父亲和母亲的特性
"""

class A:
    def test(self):
        print('test 方法')
class B:
    def demo(self):
        print('demo 方法')
class D:
    def haha(self):
        print('!!!!!!!!!!!!')
class C(A,B,D):
    """多继承可以让子类对象,同时具有多个父类的属性和方法"""
    pass

c = C()
c.test()
c.demo()
c.haha()
"""
多继承的注意事项:
问题的提出:
如果不同的父类中存在同名的方法,子类对象在调用方法时,会调用哪一个父类中的方法呢?
提示:开发时,应尽量避免这种容易产生混淆的情况
如果父类之间存在同名的属性或方法,因该尽量避免使用多继承
看的是父代排序
"""
class A:
    def test(self):
        print('A----test 方法')
    def demo(self):
        print('A----demo 方法')

class B:
    def test(self):
        print('B----test 方法')
    def demo(self):
        print('B----demo 方法')


class C(B,A):
    pass

class D(A, B):
    pass


c = C()
c.test()
c.demo()
d = D()
d.test()
d.demo()

在这里插入图片描述

"""
新式类和旧式(经典)类:
object是Python为所有对象提供的基类,提供有一些内置的属性和方法,可以使用dir函数查看
新式类:以object为基类的类,推荐使用
经典类:不以object为基类的类,不推荐使用
在python3.X中定义的类时,如果没有指定父类,会默认使用object作为基类--python3.x中定义的类都是新式类
在python2.x中定义类时,如果没有指定父类,则不会以object作为基类
####推荐使用新式类#############

新式类和旧式类在多继承时---会影响到方法的搜索顺序

为保证编写的代码能够同时在python2.x和python3.x运行
今后在定义类时,如果没有父类,建议统一继承自object

"""
调用过多情况如:
一个grandson调用了很多次parent类
class Parent(object):
    def __init__(self,name):
        print('parent的init开始被调用')
        self.name = name
        print('parent的init结束被调用')

class Son1(Parent):
    def __init__(self,name,age):
        print('Son1的init开始被调用')
        self.age = age
        Parent.__init__(self,name)
        print('Son1的init结束被调用')

class Son2(Parent):
    def __init__(self,name,gender):
        print('Son2的init开始被调用')
        self.gender = gender
        Parent.__init__(self,name)
        print('Son2的init结束被调用')

class Grandson(Son1,Son2):
    def __init__(self,name,age,gender):
        print('grandson的init开始被调用')
        Son1.__init__(self,name,age)
        Son2.__init__(self,name,gender)
        print('grandson的init结束被调用')


gs = Grandson('grandson',18,'男')
print('姓名:',gs.name)
print('年龄:',gs.age)
print('性别:',gs.gender)

在这里插入图片描述

新式类:调用的顺序为广度优先
旧式类:调用顺顺序为深度优先
super()类:不重复的调用父类,解决了钻石继承(多继承)的难题
优化方法就是运用super,如:
class Person(object):
    def __init__(self):
        print('我要好好学习')
    def study(self):
        print('我要好好学习语言')

class Man(Person):
    def __init__(self):
        print('我是男的我要好好学习')
    def study(self):
        print('我要学好数学')
        #super().study()
class Womam(Person):
    def __init__(self):
        print('我是女的我要好好学习')
    def study(self):
        print('我要学好英语')
        super().study()

class Son(Man,Womam):
    def __init__(self):
        print('我是儿子我要好好学习')

    def study(self):
        print('我要学好化学和物理')
        #Womam.study(self)
        #Man.study(self)
        super().study()
print(Son.mro())
son1 = Son()
son1.study()

在这里插入图片描述

"""
super实现原理:通过c3算法,生成mro(method resolution order)列表,根据列表中元素顺序查询调用
super()不是指父类 而是指以实例化对象为起点的mro序列中的下一个
  
简洁点的三个原则就是:
子类在父类前,所有类不重复调用,从左到右
"""
在下面可以测试:
class A():
    def go(self):
        print ("go A go!")
    def stop(self):
        print ("stop A stop!")
    def pause(self):
        raise Exception("Not Implemented")
class B(A):
    def go(self):
        super(B, self).go()
        print ("go B go!")
class C(A):
    def go(self):
        super(C, self).go()
        print ("go C go!")
    def stop(self):
        super(C, self).stop()
        print ("stop C stop!")
class D(B,C):
    def go(self):
        super(D, self).go()
        print ("go D go!")
    def stop(self):
        super(D, self).stop()
        print ("stop D stop!")
    def pause(self):
        print ("wait D wait!")
class E(B,C):
    pass

a = A()
b = B()
c = C()
d = D()
e = E()
"""
私有属性和私有方法
应用场景及定义方式
应用场景
	在实际开发中,对象的某些属性或方法可能只希望在对象的内部使用,而不希望在外部被访问到
	私有属性 就是 对象 不希望公开的 属性
	私有方法 就是 方法 不希望公开的 方法
定义方法
	在定义属性或方法时,在属性名或者方法名前增加两个下划线,定义的就是私有属性或方法
"""
class Women(object):
    def __init__(self,name):
        self.name = name
        self.__age = 18

    def __secret(self):
        print('%s 的年龄是 %d' %(self.name,self.__age))

lily = Women('lily')
#print(lily.__age)
lily.__secret()

在这里插入图片描述

静态和实例
class Date(object):
    def __init__(self,year,month,day):
        self.year = year
        self.month = month
        self.day = day
    # 实例方法(默认情况下会传递对象给echo方法)
    def echo(self):
        print('%s %s %s' %(self.year,self.month,self.day))

    # 默认传递类本身给这个方法
    @classmethod
    def as_string(cls,s):
        #print(cls)
        month,day,year = s.split('/')
        d = cls(year,month,day) # d = Date(2018,10,10)
        return d
# 静态方法:不需要创建对象,直接就可以使用
    @staticmethod
    def is_vaild(s):
        # 批量将年月日转换成整型
        # month,day,year = s.split('/')
        # month,day,year = [int(i) for i in s.split('/')]
        month,day,year = map(int,s.split('/'))
        return 0<month<=12 and 0<day<=31 and 1<year< 9999

d = Date(2018,10,10)
d.echo()


s = '10/10/2018'
Date.as_string(s).echo()
print(Date.is_vaild(s))

在这里插入图片描述

"""
一切皆对象
类也是一个特殊的对象-->类对象
类属性
类方法
"""
"""
需求:定义一个工具类
每件工具都有自己额名字
需要知道使用这个类,创建了多少个工具对象
"""
class Tool(object):
    # 1.使用赋值语句定义类属性,记录所有工具的数量
    count = 0

    def __init__(self,name):
        self.name = name
        # 让类属性的值 +1
        Tool.count += 1
    @classmethod
    def show_tool_count(cls):
        # cls.count 在类方法内部,访问当前的类属性
        print('工具对象的数量 %d' %(cls.count))

# 创建工具对象(对象在创建的时候,会自动调用初始化方法)
#print(Tool.count)
tool1 = Tool('斧头')
#tool2 = Tool('榔头')
tool1.show_tool_count()
# 输出工具对象的属性
# 使用 类名.属性名 的方式来获取属性名
#print(Tool.count)
类是一个特殊的对象
Python中一切皆对象
	class AAA: 定义的类属性属于类对象
	obj1 =AAA: 属于实例对象
在运行程序时,类 同样会被加载到内存
在python中,类 是一个特殊的对象--类对象
在程序运行时,类对象(模板) 在内存中之有一份,使用一个类(模板)可以创建出很多个对象实例
除了封装 实例 的属性和方法外,类对象还可以有自己的属性和方法
1.类属性
2.类方法
通过 类名. 的方式可以直接访问类的属性或者调用类的方法


类方法需要用修饰器@classmethod来标示,告诉解释器这是一个类方法
类方法的第一个参数应该是cls
	由哪一个类调用的方法,方法内的cls就是哪一个类的引用
	这个参数和实例方法的第一个参数是self类似(哪一个对象调用的方法,self就是哪一个对象的引用)

通过类名调用类方法,调用方法时,不需要传递cls参数

在方法内部
	也可以通过cls.访问类的属性
	也可以通过cls.调用其他的类方法

猜你喜欢

转载自blog.csdn.net/GLH_2236504154/article/details/85269073