ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Python编程学习-基础笔记06

2022-07-11 15:03:28  阅读:91  来源: 互联网

标签:__ 06 name Python self 编程 print age def


八、面向对象

8.1 面向对象基础

面向对象:是将一组具有共同特征的事物,将其抽象出来,作为基类,然后再以类为模板去创建具体的对象。比如学生是一个类,而具体到某位同学则是对象,他们具有共同的学生类特征。

8.1.1 类和对象的定义示例:

'''
面向对象:
程序   vs   现实
对象 ----> 具体的事物
现实中事物 --> 转化为程序  : 世间万物皆对象
好处:
    类
    对象
    属性
    方法
对象:
    xxx的手机
    对象的集合 --> 共同点:
                    动作:打电话、发短信、上网.... --> 方法
                    特征:品牌、颜色、大小、价格... --> 属性
    类别:手机类
多个对象 --》 提取对象的共同特征和动作 --》封装到一个类中
'''
#类名要求首字母大写,多个单词用驼峰式 ValueError,
#定义类和属性
#定义类
class Student():
    #类属性
    name = 'jack'
    age = 10
#使用类来创建对象 对象 = 类名()
jack = Student()
jack.age  = 18 #对象属性
print(jack.age) #先找自己空间的,如果没有,然后再去类中查找
print(jack.name)
jack.gender = 'Male'

8.1.2 构造器

类中的方法:动作

'''
类中中的方法:动作,
种类:普通方法(函数),类方法,静态方法,魔术方法
普通方法格式:
    def 方法名(self,[选填参数]):
        pass
类方法:
class 类名:
    def 方法名(self):
        pass
'''
#
class Phone(): #默认继承object
    #属性
    brand = 'Huawei'
    price = 5399
    type = 'Mate40Pro'
    #方法
    def call(self): #self 获取到的是函数内存地址
        print('self---->',self) #self----> <__main__.Phone object at 0x0000023B8DC9A6A0>,基于函数调用而不断变化
        print('正在访问通讯录')
        for person in self.address_book: #phone2没有定义address_book,调用则会报错,这里是不能保证每个self中都存在address_book
            print(person.items())

        print('正在打电话……')
        print('留言:',self.note) #不能保证每个self中都存在note

phone1 = Phone()
phone1.note = '我是phone1 的note'
phone1.address_book = [{'13888889999':'Jack'},{'13888889991':'Lucy'}]
print(phone1.brand)
print(phone1,'*****1*****') #<__main__.Phone object at 0x0000023B8DC9A6A0> *****1*****
phone1.call() #call(phone1) --> self.note

phone2 = Phone()
phone2.note = '我是phone2 的note'
print(phone2.brand)
print(phone2,'******2****') #<__main__.Phone object at 0x0000024314FDA630>  *****2*****
phone2.call() #call(phone2) --> self.note

8.1.3 初始化对象

在类中定义魔术方法,对象调用时动态改变其参数。

# 类中的方法
class Phone(): #默认继承object
    #魔术方法之一,称作魔术方法:__名字__()
    def __init__(self): #初始化
        print('----------------init')
        #动态的给self空间添加2个属性brand 和 price
        self.brand = 'Huawei'
        self.price = 3999
    def call(self): #self不断发生变化
       print('---------->call')
       print('---------->price:',self.price) #不能保证每个self都有price

'''
1,p先去内存中找有没有一块空间叫Phone;
2,利用Phone类,向内存申请一块跟Phone一样的空间;
3,去Phone中去找方法__init__
    如果没有,则执行将开辟的内存给对象p
    如果有,则进入__init__方法,执行里面的动作,这里self得到的地址是p的地址,执行完成后,将地址赋值给对象p
'''
p = Phone() #
p.price = 3000 #可修改初始值
p.call() #p.call()  p是对象

p1 = Phone()
p1.call()

8.1.4 对象方法

class Person:
    name = 'Forrest'
    # #不带参数
    # def __init__(self): #保证每个对象空间都有 name 和age
    #     self.name = 'Lucy'
    #     self.age = 18
    #带参数
    def __init__(self,name,age): #保证每个对象空间都有 name 和age
        self.name = name
        self.age = age
    #不带参数
    # def eat(self): #公共的动作,函数调用才不会有阴影
    #     print(f'{self.name} is eating Apple')
    #带参数
    def eat(self,food): #公共的动作,函数调用才不会有阴影
        print(f'{self.name} is eating {food}')

    def run(self): #self.gender不是公共动作,pycharm报阴影
        print(f'{self.name}正在跑步,{self.age}岁了,性别:{self.gender}')
#创建对象p
p = Person('唐力',25)  #这里传的参数给init
p.name = 'Tony'
p.eat('Orange') #这个给对应的函数
p.gender = 'Female'
p.run()

#创建对象p1
p1 = Person('摩卡',18)
p1.name = 'Mobi'
p1.eat('Peach')

8.1.5 类方法

8.1.5.1 基础方法
'''
类方法
特点:
    1,定义需要依赖装饰器@classmethod
    2,类方法中的参数不是一个对象,而是类
        print(cls) #<class '__main__.Dog'> 这里打印的是Dog类
    3,类方法中只可以使用类属性
    4,类方法中是否可以使用普通方法? --> 不能
作用:
    1,因为只能访问类属性和类方法,所以可以在对象创建之前,如果需要去完成一些动作/功能,可以将器放在类方法中
    2,不依赖于对象
'''

class Dog:
    def __init__(self,nickname):
        self.nickname = nickname

    def run(self): # self 对象去调用
        print(f'{self.nickname}在院子里跑来跑去……')

    def eat(self):
        print(f'{self.nickname} is eating delicious food……')
        self.run() #类方法中的调用,需要通过 self.func()

    #装饰器
    @classmethod
    def test(cls): #cls class 类去调用
        print(cls) #<class '__main__.Dog'> 这里打印的是Dog类
        # print(cls.nickname) # 类里没有定义nickname,报错AttributeError: type object 'Dog' has no attribute 'nickname'

d = Dog('Penny')
d.run()
d.test() #会出错
8.1.5.2 补充方法
'''
类方法:补充方法
'''
class Person:
    # age = 18 #类里公共的,外部可以访问调用
    __age = 18 #加__ 私有化,只能在类内部调用

    def show(self):
        print('---------->',Person.__age)

    @classmethod
    def update_age(cls):
        cls.__age = 20
        print('----》类方法')

    @classmethod
    def show_age(cls):
        print('修改后的年龄是:',cls.__age)

#直接调用类,不依赖于对象
Person.update_age()
Person.show_age()

8.1.6 静态方法

'''
静态方法:类似于类方法
    1,需要装饰器 @staticmethod
    2,静态方法无须传递任何参数(self,cls)
    3,只能访问类的属性和方法,对象的方法无法访问
    4,加载时机同类方法
'''
class Person:
    __age = 18 #加__ 私有化,只能在类内部调用

    def __init__(self,name):
        self.name = name

    def show(self):
        print('---------->',Person.__age)

    @classmethod
    def update_age(cls):
        cls.__age = 20
        print('----》类方法')

    @classmethod
    def show_age(cls):
        print('修改后的年龄是:',cls.__age)

    @staticmethod
    def test():
        print('---->静态方法')
        # print('--->',self.name) #语法错误,没有self
        print(f'--->',Person.__age) # 只能通过类来调用

#直接调用类,不依赖于对象
Person.update_age()
Person.show_age()
Person('Jack').test() #调用静态方法

8.1.7 总结

类方法  和 静态方法
    不同:
        1,装饰器不同
        2,参数不同,类方法有参数,静态方法无参数
    相同:
        1,只能访问类的属性和方法,对象的方法无法访问
        2,都可以通过类名访问
        3,都可以在创建对象之前使用,因为都不依赖于对象
	
普通方法与两者的区别
    不同:
        1,没有装饰器
        2,普通方法要依赖于对象,因为每个普通方法都有self,self 表示对象本身
        3,只有创建了对象,才可以调用普通方法,否则无法调用

8.2 魔术方法

魔术方法是一个对象/类中的方法,和普通方法的唯一不同是:普通方法需要调用,而魔术方法是在特定的时刻自动触发。

'''
魔术发方法:
    1, __init__, 初始化,
        触发时机:初始化对象时触发,(不是实例化触发,但是和实例化在一个操作中)
    2,__new__ 实例化的魔术方法
        触发时机:实例化对象时触发
    3,__call__ 对象调用方法
        触发时机:把对象当函数调用时触发,会默认调用此函数中的内容
    4,__del__虚构魔术方法, delete的 缩写,使用默认,建议不要自己写
        触发时机:当对象没有用的时候触发。(没有任何变量引用 )
            1,对象赋值
                p = Person('Jack')
                p1 = p
                p2 = p
                说明:p,p1,p2指向同一个地址
            2,删除地址引用
                del p2  删除p2对地址的引用
            3,查看对地址的引用次数
                sys.getrefcount(p)
            4,当一块空间没有变量引用,默认执行__del__ 动作, ref = 0
                程序运行到最后,也会默认执行__del__ 动作,释放所有的内存占用,类似垃圾回收机制
                --》python解释器,回收所有在本次执行过程用到的空间,这是pyhton底层自带的
'''
import sys
class Person:
    def __init__(self,name):
        print('---------> init',self) #0x0000026751CB2588
        self.name = name

    def __new__(cls, *args, **kwargs): #向内存要空间 --》 内存地址
        print('---------> new')
        position = object.__new__(cls) # 获取到内存地址
        print(position) #<__main__.Person object at 0x0000026751CB2588>
        return position #地址
        # return super(Person, cls).__new__(cls)
    #把对象当函数调用时执行
    def __call__(self, name):
        print('---------->call')
        print('得到的参数是:',name)

    def __del__(self):
        print('----------del-----------')

p = Person('Jack')
#程序先执行__new__, 然后执行__init__
print(p) #<__main__.Person object at 0x0000026751CB2588>,不加str方法,打印的时地址
#对象当函数调用,必须要重新__call__函数
p('Jerry')
#del的引用
p1 =p
p2 = p
print(p1.name)
print(p2.name)
p.name = 'Tom'
del p2
print('删除p2后:',p.name)
del p1
print('删除p1后:',p.name)
#查看p的引用次数
del p
#p已经彻底被删除,这时调用__del__,然后再执行下面的代码,如果没有del p,会在打印print(n) 之后再执行__del__
# print(sys.getrefcount(p))

n = 2
print(n)

总结

'''
魔术发方法:
    5,__str__ , 触发时机:打印对象名时,自动触发去调用__str__里的内容
        单纯打印对象名称,出来的是一个内存地址,这对开发者意义不大
        如果想打印对象名时,给开发者更多的信息量
        注意:一定要在方法中添加return,return之后的内容,就是打印对象看到的内容

'''
import sys
class Person:
    def __init__(self,name,age):
        # print('---------> init',self)
        self.name = name
        self.age = age

    def __str__(self):
        return '姓名:'+ self.name + '年龄:' + str(self.age)


p = Person('Jack',20)
#程序先执行__new__, 然后执行__init__
print(p) #<__main__.Person object at 0x0000026751CB2588>,不加str方法,打印的时地址,加之后,打印Jack

'''
总结:魔术方法
重点: 
    __init__  构造方法,创建完空间之后调用的第一个方法
    __str__ 打印对象更多信息
了解: 
    __new__ 作用:开辟地址空间,建议不需要去重写
    __del__ 作用:没有指针引用时,回收地址空间,建议不需要去重写
    __call__ 作用:对象当函数使用,根据需要来决定是否重写    
'''

8.3 面向对象编程

#猫类
class Cat:
    type = 'cat'
    #初始化特征
    def __init__(self,nickname,age,color):
        self.nickname = nickname
        self.age = age
        self.color = color

    def eat(self,food):
        print(f'{self.nickname} like to eat {food}')

    def catch_mouse(self,color,weight):
        print(f'{self.nickname} caught one mouse which is {color} and {weight}kg ')

    def cat_sleep(self,hours):
        if hours < 5:
            print('Please keep sleeping')
        else:
            print('Get up quickly to catch mouse')
    def cat_show(self):
        print('Show the details of the Cat')
        print(self.nickname,self.age,self.color)
#创建对象
cat1 = Cat('Jerry',2,'White')
#通过对象去调用方法
cat1.catch_mouse('black',2)
cat1.cat_sleep(8)
cat1.eat('golden fish')
cat1.cat_show()

标签:__,06,name,Python,self,编程,print,age,def
来源: https://www.cnblogs.com/orange2016/p/16456890.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有