有关python的class以及self的总结

一、Python 的类和实例

在面向对象中,最重要的概念就是类(class)和实例(instance),类是抽象的模板,而实例是根据类创建出来的一个个具体的 “对象”。

就好比,学生是个较为抽象的概念,同时拥有很多属性,可以用一个 Student 类来描述,类中可定义学生的姓名、分数等属性,但是没有具体的数值。而实例是类创建的一个个具体的对象, 每一个对象都从类中继承有相同的方法,但是属性值可能不同,如创建一个实例叫 xiaowang 的学生,其分数为 93,则这个实例拥有具体的数值。

  • 类:以Student类为例,在Python中,定义类如下:
class Student(object):
  def __init__(self,name,score):
    self.name=name
    self.score=score
'''
a.(object)表示的是该类从哪个类继承下来的,而object类是每个类都会继承的一个类。 
b. __init__ 方法的第一参数永远是 self,用来表示类创建的实例本身,因此,在 __init__ 方法内部,就可以把各种属性绑定到self,因为self 本身就是指向创建的实例本身。
c. 有了 __init__ 方法后,在创建实例的时候,就不能传入空参数,必须传入与 __init__ 方法匹配的参数,但self本身不需要传入参数,只需要传入 self 后面的参数即可。
'''
  • 实例: 定义好了类后,就可以通过Student类创建出 Student 的实例,创建实例是通过 类名 ()实现:
student = Student('xiaowang', 93)
 
>>> student.name
"xiaowang"
>>> student.score
93
'''
a. 其中 Student 是类名称,('xiaowang',93)为要传入的参数
b. self.name 就是 Student类的属性变量,为 Student 类所有。同时, name 是外部传进来的参数,不是 Student 类所自带的。故 self.name = name 的意思就是把外部传来的参数 name 的值赋值给 Student类自己的属性变量 self.name .
'''
  • 和普通函数相比,在类中定义函数只有一点不同,就是第一参数永远是类的本身实例变量 self, 并且调用时,不用传递该参数。 除此之外,类的方法(函数)和普通函数没有啥区别。既可以用 默认参数、可变参数或者关键字参数等。

二、类 以及 实例的访问

  • 限制外部对类实例属性的访问
    既然 Student 类实例本身就拥有这些属性的数据,那么要访问这些数据,就没必要从外面的函数去访问,而可以在类的内部定义访问数据的函数,这样,就可以把 ”数据“ 封装起来了。这些封装数据的函数和 Student 类本身是相关联的,称之为类的方法:
class Student(obiect):
  def __init__(self, name, score):
    self.name = name
    self.score = score
  def print_score(self):
    print "%s: %d" % (self.name, self.score)

>>> student= Student("xiaowang",93)
>>> student.print_property()
xiaowang:93
'''
由此可见,从外部看Student类,我们只知道创建实例需要给出 name 和 score。究竟如何打印,是 Student 类内部定义的,这些数据和逻辑被封装起来了,调用也就变得容易了,但是不知道内部实现的细节。
'''

如果不想让实例中的内部属性被外部属性访问,则把 name 和 score 变成 __name 和 __score 即可,如下代码所示:

class Student(object):
 
  def __init__(self, name, score):
    self.__name = name
    self.__score = score
  def print_property(self):
    print "%s: %d" %(self.__name,self.__score)

>>> student= Student("xiaowang",93)
>>> student.print_property()
>>> student.__name()
xiaowang:93
Traceback (most recent call last):
AttributeError: 'Student' object has no attribute '__name'
  • 通过API,外部代码能够访问到里面的属性,并且对其进行修改

外部代码访问类里面的实例属性:

def __init__(self,name,score):
  self.__name=name
  self.__score=score
def print_property(self):
  print("%s:%d"%(self.__name,self.__score))
 
def get_name(self):
  return self.__name
 
def get_score(self):
  return self.__score 

name=student.get_name()
score=student.get_score()
print ("%s,%d" % (name,score))

外部代码修改类里面的实例属性:

def __init__(self,name,score):
  self.__name=name
  self.__score=score
def print_property(self):
  print("%s:%d"%(self.__name,self.__score))
 
def reset_name(self,change_name):
  self.__name = change_name
 
def reset_score(self, change_score):
  self.__score = change_score 

student= Student("xiaowang",93)
student.print_property()
student.reset_name("simona")
student.reset_score(91)
name=student.get_name()
score=student.get_score()
print ("%s:%d" % (name,score))
 
 xiaowang:93
simona:91

需要注意的是,在Python中,变量名类似 __xxx__的,也就是双下划线开头,并且以下划线结尾的,是特殊变量,不是private变量,特殊变量是可以直接访问的。

三. self 的详细用法

# self代表类的实例,而非类。
class Student(object):
  def print_self(self):
    print(self)
    print(self.__class__)

student=Student()
student.print_self()
 
<__main__.Student object at 0x7fd9095aed90>
<class '__main__.Student'>

从上面例子可得,self代表的只是类的实例,而 self._class _ 才是类。

定义类的时候,self最好写上,因为它代表了类的实例。在继承时,传入的是哪个实例,就是那个传入的实例,而不是指定义了self的类的实例。

class Teacher(object):
  def __init__(self,teacher):
    self.teacher=teacher
    print(self.teacher)
 
  def print_self(self):
    print(self)
 
class Student(Teacher):
  def __init__(self,student):
    self.student=student    
    print(self.student)
 
  def print_self_1(self):
    print(self)

teacher=Teacher("hansry")
student=Student("simona")
student.print_self_1()
student.print_self()
 
hansry
simona
<__main__.Student object at 0x7fd9095b0950>
<__main__.Student object at 0x7fd9095b0950>

在运行 student.print_self() 的时候,这里是调用了 类 Teacher 的 print_self() 函数,此时虽然调用的是类Teacher的函数,但是此时的实例 self 却是 类 Student 实例化时生成的。

self可以不写吗?

在Python解释器的内部,当调用t.print_self()时,实际上Python解释成Teacher.ppr(t),也就是把self替换成了类的实例。若print_self()方法里没有self参数,如下:

class Teacher(object):
  def __init__(self,teacher):
    self.teacher=teacher
    print(self.teacher)
 
  def print_self():
    print(self)
 
t=Teacher("hansry")
t.print_self()

TypeError: print_self() takes 0 positional arguments but 1 was given
运行时提醒错误如下:print_self()在定义时没有参数,但是运行时强行传了一个参数。
由于上面解释过了t.print_self()等同于Teacher.ppr(t),所以程序提醒多传了一个参数t。
这里实际上已经部分说明了self在定义时不可以省略。

selfPython中是一个约定俗成的关键字,它代表类的实例。在类的方法中,self作为第一个参数传递,指向调用该方法的实例对象。通过self可以访问实例的属性和方法。同时,self.__class__指向类本身,可以用于访问类的属性和方法。 在Python解释器内部,当我们调用一个实例对象的方法时,实际上Python会将方法的调用转换为类名.方法名(实例对象)的形式,即将self替换为类的实例对象。 例如: ```python class Test: def ppr(self): print(self) t = Test() t.ppr() ``` 输出结果为: ``` <__main__.Test object at 0x000000000284E080> ``` 在描述符类中,self指的是描述符类的实例。描述符是一种特殊的类,用于控制对类属性的访问。在描述符类的__get__方法中,self表示描述符类的实例,ins表示调用描述符的实例对象,cls表示调用描述符的类。 例如: ```python class Desc: def __get__(self, ins, cls): print('self in Desc: %s ' % self) print(self, ins, cls) class Test: x = Desc() def prt(self): print('self in Test: %s' % self) t = Test() t.prt() t.x ``` 输出结果为: ``` self in Test: <__main__.Test object at 0x000000000284E080> self in Desc: <__main__.Desc object at 0x000000000284E1D0> <__main__.Desc object at 0x000000000284E1D0> <__main__.Test object at 0x000000000284E080> <class '__main__.Test'> ``` 总结起来,selfPython的类中代表类的实例,可以用于访问实例的属性和方法。同时,self.__class__指向类本身,可以用于访问类的属性和方法。在描述符类中,self指的是描述符类的实例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值