Python之旅的第20天(class和实例对象)

内功心法果然和基本功没关系,绕来绕去的确实很容易懵,所以今天内容其实不多,但是各种试错还是很多的

一、class知识的继续补充

关于class的一些应该说明的本质问题
还是以狗狗为例
class Dog:
    '这里一般放置关于这个类的描述,还是应该专业点,这是一个狗狗的类'

    def __init__(self, name, gender, age, type):
        self.name = name
        self.gender = gender
        self.age = age
        self.pinzhong = type
    __init__函数是不能又返回值的,如果你强行返回,系统会告诉你你错了
    没有return

    下面就可以定义一些关于狗的方法了
    def xiaogou(self):
        #这里你会发现当你定义了一个函数之后,class会自动要求把你在__init__中的self作为变量传输进去
        print('%s的狗才能生小狗'%self.gender)

    def jiao(self):
        print('%s正在汪汪汪叫'%self.name)

    def chishi(self):
        print('%s岁之后狗才会吃屎'%self.age)

    def yang(self):
        print('%s容易掉毛'%self.pinzhong)

dog1 = Dog('旺财','woman','5','金毛')
这里这句其实相当于在执行类Dog,输入参数的过程和函数没有区别
上面这一句做的事情其实和下面这句是一样的
dog1 = Dog.__init__(dog1,'旺财','woman','5','金毛')
当你在执行Dog的时候其实就是__init__方法,他会默认将dog1传给self
这一步就是对象的实例化的过程
print(dog1)
print(dog1.__dict__)
{'pinzhong': '金毛', 'gender': 'woman', 'age': '5', 'name': '旺财'}
你会发现当一个类实例化之后,功能属性(即函数)不在上述字典中
但是Dog类里面还是在的哦
print(Dog.__dict__)
{'__module__': '__main__', 'chishi': <function Dog.chishi at 0x000001F3123A4598>,
'__init__': <function Dog.__init__ at 0x000001F3123A40D0>, '__dict__': <attribute '__dict__' of 'Dog' objects>,
'__doc__': '这里一般放置关于这个类的描述,还是应该专业点,这是一个狗狗的类', '__weakref__': <attribute '__weakref__' of
'Dog'objects>, 'jiao': <function Dog.jiao at 0x000001F3123A4510>, 'yang': <function Dog.yang at 0x000001F3123A4620>,
'xiaogou': <function Dog.xiaogou at 0x000001F3123A4488>}
此时你是否看到,我们在输出对象的字典的时候是只有数据属性部分的
那么如何调用功能属性呢
先是使用老式方法开始
Dog.__dict__['yang'](dog1)
准确的输出了:金毛容易掉毛
但是这种方法太low了,现在的class类可以帮我们实现
dog1.yang()
这里也是输出了:金毛容易掉毛
但是你会发现,yang这个函数是需要你传递一个参数self的
这里传递参数由class协助完成,会默认将__init__方法形成的对象传入其中
如果使用老方法不传参数会怎样呢
Dog.__dict__['yang']()
这个时候就会报错:TypeError:yang() missing 1 required positional argument: 'self'
说你没传参数
还有就是关于class里面的作用域问题
之前我们提到,如果个变量找不到自己的值,会不停往外找,直到找到为止,但是在class中
如果找到class的最外层还没找到就不会找了
重新来一个类验证一下吧

dang = ''
class Chinese:
    pep = ''
print(Chinese.dang)  #输出:党
但是我们把党注释掉,放到class外面
print(Chinese.dang)
此时会报错:AttributeError: type object 'Chinese' has no attribute 'dang'

二、类的增删改查

类的增删改查
class Chinese:
    'Chinese类,增删改查测试'
    country = 'China'
    def __init__(self,name):
        self.xingming = name

    def play(self,ball):
        print('%s正在打%s'%(self.xingming,ball))

类的增加,首先是数据属性的增加
Chinese.goverment = '党'
p1 = Chinese('alex')
print(p1.country , p1.goverment)
输出:China 党  完成增加新的数据属性的增加

类的增加,关于增加功能属性的部分
def test(self):
    print('这是测试部分的内容')
Chinese.test_add = test
p1.test_add()   #这是测试部分的内容

删除类的功能,我们就删除掉上面刚才新增的类
del Chinese.test_add
del Chinese.goverment
print(Chinese.__dict__)
{'__init__': <function Chinese.__init__ at 0x00000200A8DC40D0>, '__weakref__': <attribute '__weakref__' of 'Chinese' objects>,
'play': <function Chinese.play at 0x00000200A8DC4488>, 'country': 'China', '__doc__': 'Chinese类,增删改查测试',
'__dict__': <attribute '__dict__' of 'Chinese' objects>, '__module__': '__main__'}
此时刚才新增的两个数据属性和功能属性就都删除掉了

关于类的修改,其实修改的方式和新增的方式是类似的
Chinese.country = '小日本'
def eat_food(self , food):
    print('%s在吃 %s'%(self.xingming , food))
Chinese.play = eat_food
print(p1.country)   #输出:小日本
p1.play('xiang')
输出:alex在吃 xiang

查看,就直接用类.属性名直接调用查看就可以了

三、实例对象的增删改查

# 实例对象的增删改查
# class Dog:
#     '测试实例对象的增删改查,包括他的功能属性的修改'
#     def __init__(self,name):
#         self.name = name
#
#     def wang(self,people):
#         print('%s正在冲着%s汪汪叫'%(self.name , people))
#
# p1 = Dog('wangcai')
# print(p1.name)  #wangcai
# p1.name = '旺财'
# print(p1.name)   #旺财

# p1.wang('如花')  #旺财正在冲着如花汪汪叫
# def yaoweiba(self , people):
#     print('%s正在对着%s摇尾巴' % (self.name, people))
# p1.wang = yaoweiba
# p1.wang(p1,'如花') #旺财正在对着如花摇尾巴
# 上面这一句需要注意的是,因为这里修改的是针对p1的功能属性,之前p1是没有功能属性的,他的功能属性是调用Dog类的功能属性
# 这里进行修改之后,对类里面的功能并没有影响,所以新增的功能也不具备class优越性,所以我们不仅需要传递参数people,还需
# 要传递参数self,此时我如果使用另一个对象实例去调用Dog的wang方法,结果还是之前的
# p2 = Dog('小白')
# p2.wang('美伢')   #小白正在冲着美伢汪汪叫
# 所以针对实例对象的功能属性修改是没有实际意义的
# 也不提倡使用

四、接下来是些比较有意思的东西,看着蛮有意思的,但是想多了反而更容易错,先记录在这里吧

# 下面是一些关于class模块和平时的局部作用域的奇葩案例,加深理解

# country = '外国'
# class China:
#     country = '中国'
#     def __init__(self,name):
#         print(country)
#         self.name = name
#
#     def kaixin(self):
#         print('%s今天很开心'%s)
#
# p1 = China('马云')
# 对China类进行实例化生成实例对象的过程中,在__init__函数下的print输出的country
# 输出结果是'外国'
# print(p1.country)   #而此处的country是中国

# 上面这个例子就反应了一个问题,country = '中国' 是作为一个类的属性保存在China类中,如果我们以类名.属性名,
# 或者实例对象.属性名调用时,会在China类中查看属性对应的值,而__init__中的print语句输出的country只是一个单
# 纯的变量,虽然近在眼前的就是country = '中国'  但是,这部分是属于类的属性的

# 下面是关于修改的范围
# p2 = China('alex')
# print(p2.country)
# p2.country = '日本'
# print('class的是',China.country)
# print('实例对象',p2.country)
# class的是 中国
# 实例对象 日本
# 可以明显看处p2.country修改了属性对class不会有任何影响

# 接下来是一个比较狠的
class Test:
    '测试类'
    a = ['a','b']
    def __init__(self,name):
        self.name = name

p1 = Test('alex')
# p1.a = ['a','b','c']
print('实例对象',p1.a)
print('Test类的',Test.a)
# 实例对象 ['a', 'b', 'c']
# Test类的 ['a', 'b']
# 这样修改其实是相当于新建了一个p1.a的列表
# 如果修改换种方式呢
p1.a.append('c')
print('实例对象',p1.a)
print('Test类的',Test.a)
# 实例对象 ['a', 'b', 'c']
# Test类的 ['a', 'b', 'c']
# 这里其实是直接在列表a上面进行修改,导致类的发生了变化

今天的内容就是这些了,class部分告一段落,这个功能的确很强大,之前的内容完全都被他整合了。

我擦,吐槽一下,敏感词汇,没想到这还有。。。

posted @ 2020-03-14 01:05  崆峒山肖大侠  阅读(200)  评论(0编辑  收藏  举报