关于类
1.2021年2月15日13:01:03>>> class Student(object):
pass
>>> bart = Student()
>>> Student
<class '__main__.Student'>
>>> class S(object):
pass
>>> S
<class '__main__.S'>
>>> bart
<__main__.Student object at 0x0000018F96999D30>
>>> bart.name = 'bart simpson'
>>> bart.name
'bart simpson'
>>>
这还能直接加name吗? 当然可以啊
而且如果是提问,请发提问帖 qiuyouzhi 发表于 2021-2-15 13:16
当然可以啊
而且如果是提问,请发提问帖
{:10_254:}哈哈,我我我我的本意是想记录一下自己的疑问,实在不懂了再麻烦各位大哥(节省大家回答憨憨问题),谢谢你的回答!!!
另外方便的话能否告知这个能直接加name的这个操作哪里有讲,我好像没看到小甲鱼讲到。(不方便我就自己想办法,嘿嘿{:10_297:}) Python初学者8号 发表于 2021-2-15 13:18
哈哈,我我我我的本意是想记录一下自己的疑问,实在不懂了再麻烦各位大哥(节省大家回答憨憨问 ...
啊?这个我不太清楚耶..
你看看类和对象那几节课,应该会有讲的 2.2021年2月15日13:18:59
参考的是廖雪峰
啊哈哈,关于这个self我想我大概明白了一点点了。正文如下:
正文
我创建了两次类,第一次是class Student(object):
pass
然后我我按照教程开始创建第二个类
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
def print_score(self):
print('%s: %s' % (self.name, self.score))
先创建一个类,然后我想先进行实例化
>>> bart2 = Student()
Traceback (most recent call last):
File "<pyshell#78>", line 1, in <module>
bart2 = Student()
TypeError: __init__() missing 2 required positional arguments: 'name' and 'score'
>>> bart2 = Student(syd,99)
Traceback (most recent call last):
File "<pyshell#79>", line 1, in <module>
bart2 = Student(syd,99)
NameError: name 'syd' is not defined
>>> bart2 = Student('syd',99)
>>> bart2
<__main__.Student object at 0x0000018F969AF070>
>>> bart2.name
'syd'
>>> bart2.score
99
>>> bart2.print_score
<bound method Student.print_score of <__main__.Student object at 0x0000018F969AF070>>
>>> bart2.print_score()
syd: 99
>>>
(1)第一个错误:bart2 = Student()
这个方法是错的,就像这个代码一样>>> def add(x,y):,然后如果我使用的这样创建就是错的jiafa = add(),因为这个函数需要参数。
如果我创建这个函数 def add():print(‘我是加法’) ,然后使用jiafa =add()就可以调用
这两种区别在于函数是否需要参数。
同样的理由,我新建的第一个Student的实例的时候,是没有自己固定的属性的(参数),所以我创建的时候不需要输入参数(默认没有固定的属性),而第二个Student则因为我需要固定参数所以才需要传入参数
正确的创建实例的方法是bart2 = Student('syd',99),当然这个syd是个字符串,不可以不加引号。
(2)第二个错误:bart2.print_score
我想按照教程使用这个实例中含有的方法来完成打印的功能,但是这失败了。问题出在没有加括号。
其实这是显而易见的,不论他是不是一个类的实例中的方法与否,print_score()的本质都是一个函数,而且还是一个需要参数的函数。
那么既然是函数就需要加括号来调用,否则仅仅“叫名字”只是在问他是谁,那么他就会回答自己是谁——也即为自己从哪里来并且身份是啥。
现在回答正题来,怎么理解self了。
我在调用bart2.print_score()的时候,按照我上面两行理解的,首先print_score()他是个函数,所以调用需要加括号。其次,这个函数是需要参数的,所以我在这里调用时候是不是也应该加一个参数呢?
但是这里没有,那么python却还是能够实现该函数的功能,并且将syd的名字和分数打印出来了。
那么,这就很显而易见了,python 的设计者使用了self这样的方法,直接将一些在这个函数中使用的参数从他的默认属性(也即为def __init__(self, name, score))中直接调用了。
这个设计很厉害 啊,很简单。就像是玩游戏一样。打比方,我现在需要一个ADC,那么我现在就要选择一个ADC,那么这个ADC需要知道它是哪个职业选手,并且要知道他的表现(评分)如何。
这个时候我作为战队的负责人我就会在队伍中选择一个好的adc(2016年msi的时候rng有无心 uzi 和还有一个我忘了三adc),然后将他的名字和分数报上去,这个时候就产生了这个具体的(实例)ADC,而不是一个概念。
我让他自报家门的时候就不用自己再介绍了(他自己会说?)
哈哈,就是这么理解一下,很傻逼,但是是我自己的理解。
3 2021年2月15日14:02:44
更加理解了这个def __init__()的作用了。
这个东西确实是一个默认的属性,赋予给他独一无二但是又是默认的属性。
我曾想,在外部定义一个数据,,内部的函数是否可以访问呢?我觉得不行, 因为还是那句话,他的本质是一个函数。现在我加上新的理解,就是,这个类本身就是一种数据的封装,包括创建出得到的那个实例也一样
a = 100
class Student():
a = 22
def __init__(self, name, score):
self.name = name
self.score = score
def get_grade(self):
if self.score >= 90:
return 'A'
elif self.score >= 60:
return 'B'
else:
return 'C'
def f1(self):
a = 1
b = 2
print(a,b)
bart = Student('syd',88)
bart.f1()
这个代码很明显,首先a =100是封装外面的数据,不会影响局部的数据。其次这个内部的a=22也是一个属性,是公用的属性,是模板的属性,那么我们给的def __init__(self, name, score):这个是想要使每个实例都有自己独一无二的参数。
所以这个设计就很机智, 就是要传递这个默认的参数,所以这些init和self就是出于这个目的实现的 4 2021年2月15日14:09:06
对于3的代码我编写了这么一段我觉得理解类也有局部变量和全部变量的这个操作会更加方便a = 1
class Student():
global a
a = 2
def __init__(self, name, score):
self.name = name
self.score = score
def get_grade(self):
if self.score >= 90:
return 'A'
elif self.score >= 60:
return 'B'
else:
return 'C'
def f1(self):
a = 3
b = 2
print(a,b)
bart = Student('syd',88)
bart.get_grade()
bart.f1()
其实还是应该回归python设计的思路,也即为,函数也好,可迭代对象也罢,亦或是类(或者实例),都是一个封装。
可迭代对象一般是封装数据,函数一般是封装逻辑(当然也包含内部的数据不过一般外部不好调用),而这个类则是集两者之大成,好家伙,他直接将前面二者直接封装,。
无外乎人家说程序就是数据和算法(逻辑)的集合,软件也就是一堆数据和逻辑而已。
大概这就是面向对象编程的刺激了 本帖最后由 Python初学者8号 于 2021-2-15 14:33 编辑
5 2021年2月15日14:14:45
新增加的理解,哈哈,如代码class Dog(object):
def __init__(self, variety, age, height, weight):
self.variety = variety
self.age = age
self.height = height
self.weight = weight
def property(self):
print(self.variety)
print('%d years old' %self.age)
print('%d cm' %self.height)
print('%d kg' %self.weight)
print('This kind of dog can destory things.')
print('This kind of dog can eat the food.')
print("This kind of dog maybe bite people.")
print('''
''')
husky = Dog('Husky', 9, 55, 25)
borderCollie = Dog('Border Collie', 12, 49, 12)
husky.property()
borderCollie.property()
a = 1
class Student():
global a
a = 2
def __init__(self, name, score):
self.name = name
self.score = score
def get_grade(self):
if self.score >= 90:
return 'A'
elif self.score >= 60:
return 'B'
else:
return 'C'
def f1(self):
a = 3
b = 2
print(a,b)
bart = Student('syd',88)
bart.get_grade()
bart.f1()
这么理解一下:
我们想要让每个内部的method都使用在实例之内但是又在函数之外的外部变量的时候,就必须找参数啊。
就像f1这个函数,首先找一下f1内部的局部变量,然后找不到a的时候就去看init中有没有(此时,这个变量必须是前缀self.),再没有的话,再看看有没有全局变量
a = 1
class Student():
global a
a = 2
def __init__(self, name, score,a):
self.name = name
self.score = score
self.a = a
def get_grade(self):
if self.score >= 90:
return 'A'
elif self.score >= 60:
return 'B'
else:
return 'C'
def f1(self):
b = 2
print(self.a,b)
bart = Student('syd',88,3)
bart.get_grade()
bart.f1()
所以这么总结吧,在类的方法中使用变量考虑两个方向,
1.一个是不加self.的变量。
函数在使用的时候会现在内部寻找(即为局部变量),找不到了再看有没有外部的全局变量。
当全局和局部的时候,那就是强龙不压地头蛇
它是一种相对来说的公共的参数,因为每个类在创建的时候就有,但是又是可以改变的(只有global的时候)
2 一个是加self.的变量
这个类变量的出现让每个类有独一无二的属性,我个人理解是避免在类的外部定义 一大堆的外部变量然后又在类中使用全局,多此一举啊!
所以就这样做,这样做很高级
设想一下,当不这么设计类这种东西的话,我们写程序就这样写
a = 1
class Student():
global a
def get_grade(self):
if self.score >= 90:
return 'A'
elif self.score >= 60:
return 'B'
else:
return 'C'
def f1(self):
b = 2
print(a,b)
##bart = Student('syd',88,3)
bart = Student()
##bart.get_grade()
bart.f1()
如果这样写,当然实现了的是逻辑的封装,那么这个和函数有什么区别吗?区别只是可以调用内部函数而已(当然可以在deffucntion后使用return f1,f2,f3实现)
但是这样的效率太低了,如果有两个实例的话,那么不是公用a吗?
所以不用这样的方法
不得不说类的设计还是很好 的
qiuyouzhi 发表于 2021-2-15 13:26
啊?这个我不太清楚耶..
你看看类和对象那几节课,应该会有讲的
好的好的,谢谢啊。{:10_257:}
页:
[1]