python学习之类class继承、super()使用和__init__初始化

类的学习、__init__学习和super方法学习

  • 1.python中类的属性、方法学习
  • 2. 类的实例方法、类方法、静态方法
  • 3.类class的访问控制:单划线_与双划线__
  • 4.继承中的__init__
  • 5.super的详细使用

1.python中类的属性、方法学习

  • 类的私有属性:以两个下划线开头的,如 __private_attrs,声明该属性为私有,不能被类的外部使用或直接访问。在类的内部方法使用时用:self.__private__attrs
  • 类的方法:与一般函数定义不同,类的方法定义的第一个参数必须为self;
  1. 类的专有方法:
方法名 作用
init 构造函数,在生成对象时调用,即初始化该方法的属性
del 析构函数,释放对象的时候使用

参考

class person(object):
	tall=180
	hobbies=[]
	def __init__(self,name,age,weight):
		self.name=name
		self.age=age
		self.weight=weight
	def information(self):
		print("%s age is %d ,and weigth is %s"%(self.name,self.age,self.weight))

person.hobbies.extend(["football","woman"]) #类数据属性属于类本身,可以通过类名进行修改和访问,此次添加两个值
print("person hobbies list is:%s"%person.hobbies)
person.hobbies2=["reading","swimming","running"] #类在定义后,依然可以添加类的属性,新增的类属性也可以被类和所以实例共有
print("person hobbies2 list is:%s"%person.hobbies2)
print(dir(person)) #通过内建函数dir()或访问类的字典属性__dict__这两种方式来查看类有那些属性

jhon=person("jhon",24,66) #实例数据属性只能通过实例化访问
jhon.gender="man"  #类实例化后可以动态添加属性,但是只能被实例化的jhon使用
print("%s gender is %s"%(jhon.name,jhon.gender))
print(dir(jhon))
jhon.hobbies.append("python") #修改实例化列表属性,在原基础上添加
infoma=jhon.information()
print(infoma)
print(jhon.hobbies)

jhon2=person("jhon2",25,68) #jhon2将没有属性gender
print(jhon2.__dir__())
  1. 特殊的类属性:对于所有的类
属性名 含义
name 类的名字
doc 类的文档字符串
bases 类的所有父类组成的元组
dict 类的属性组成的字典
module 类所属的模块
class 类对象的类型
  1. 类的隐藏属性(不可变类型的类属性)
  • 对于不可变类型的类属性person.tall,可以通过实例jhon进行访问;person.tall的值就是jhon.tall的值 。
  • 当通过实例赋值或修改属性时,将为实例jhon新建一个tall实例属性,person.tall 不等于 jhon.tall 。
  • 当通过del jhon.tall语句删除实例tall的属性后,再次成为:person.tall为jhon.tall

对于可变类型的类属性(列表等),隐藏属性总结为:

  • 同样对于可变类型的类属性person.hobbies,可以通过实例Bruce进行访问,并且"person.hobbies is Bruce. hobbies"
  • 当通过实例赋值hobbies 属性的时候,都将为实例Bruce新建一个hobbies实例属性,这时,“person.hobbies is not Bruce. hobbies”
  • 当通过"del Bruce. hobbies"语句删除实例的hobbies属性后,再次成为"person. hobbies is Bruce.hobbies"
  • 当通过实例修改hobbies属性的时候,将修改Bruce. hobbies指向的内存地址(即person.hobbies),此“person.hobbies is not Bruce. hobbies”

虽然可以通过实例化来访问类的属性,但是不建议这样做,最好通过类名访问类的属性,从而避免属性隐藏带来的不必要的麻烦

2. 类的实例方法、类方法、静态方法

  1. 实例方法
    实例方法的第一个参数必须为self,实例方法只能通过类实例化进行调用,这时的self代表这个类本身。通过self可以直接访问实例的属性:
class person(object):
	tall=180
	hobbies=[]
	def __init__(self,name,age,weight): #__init__类的私有方法,构造方法,实例类的时候调用
		self.name=name
		self.age=age
		self.weight=weight
	def infoma(self): #实例方法,只能通过实例进行调用
		print('%s is age %s weights %s'%(self.name,self.age,self.weight))
jhon=person("jhon",24,175)
jhon.infoma()
输出:
jhon is age 24 weights 175
  1. 类方法
  • 类方法以cls作为第一个参数,cls表示类本身,定义时使用@classmethod装饰器。通过cls可以访问类的相关属性
class person(object):
    tall = 180
    hobbies = []
    def __init__(self, name, age,weight):
        self.name = name
        self.age = age
        self.weight = weight
    @classmethod #类的装饰器
    def infoma(cls): #cls表示类本身,使用类参数cls
        print(cls.__name__)
        print(dir(cls))
#cls表示类本身
person.infoma() #直接调用类的装饰器函数,通过cls可以访问类的相关属性
jhon=person("jhon",24,170) #也可以通过两个步骤来实现,第一步实例化person
jhon.infoma() #调用装饰器
  1. 类的静态方法
  • 类的静态方法没有参数限制,即不需要实例参数,也不需要类参数,定义的时候使用@staticmethod装饰器
    同类方法一样,静态方法可以通过类名访问,也可以通过实例访问;
class person(object):

   tall = 180
   hobbies = []
   def __init__(self, name, age,weight):
       self.name = name
       self.age = age
       self.weight = weight
   @staticmethod    #静态方法装饰器
   def infoma():     #没有参数限制,既不要实例参数,也不用类参数
       print(person.tall)
       print(person.hobbies)
#person.infoma()   #静态法可以通过类名访问
Bruce = person("Bruce", 25,180)   #通过实例访问
Bruce.infoma() 

3.类class的访问控制:单划线_与双划线__

  • 在python中,通过单下划线来实现模块级别的私有化,除变量外。一般约定以单划线开头的函数为模块私有的,也就是说:from modulename import *将不会导入以单划线开头的函数
_tall=180  #导入该包时会导入
def _call_for(): #导入该包时不会导入
	print('_tall',——tall)
  • 对于python中的类属性,可以通过双下划线__来实现一定程度的私有化。由于双下划线开头的属性在运行时会被"混淆"
class person(object):
    
    tall = 180
    hobbies = []
    def __init__(self, name, age,weight):
        self.name = name
        self.age = age
        self.weight = weight
        self.__Id = 430 #实现__id一定程度的私有化
    @staticmethod
    def infoma():
        print(person.tall)
        print(person.hobbies)
#person.infoma()
jhon = person("jhon", 25,180)
#print(Bruce.__Id)#出错
#jhon.infoma() 
#通过内建函数dir()发现__Id属性在运行时,属性名被改成_person__Id
print(dir(jhon))
print(jhon._person__Id)
  • 双划线的另一个用途:避免子类对父类同名属性的冲突
class A(object):
	def __init__(self):
		self.__private()#将执行时会变成self._A__private()
		self.public()
	def __private(self): #只能被本身类访问,连子类也不行
		print('A.__private()')
	def public(self):
		print('A.public()')
class B(A):
	def __private(self): #
		print('B.__private()')
	def public(self):
		print('B.public()')
b=B() #当B实例化后,由于没有定义__init__函数,将会调用父类的__init__,但是由于双下划线的'混淆'效果,"self.__private()"将变成self._A__private()
输出:
A.__private()
B.public()
class A(object):
	def __init__(self):
		self.private()
		self.public()
	def private(self): 
		print('A.private()')
	def public(self):
		print('A.public()')
class B(A):
	def private(self): #
		print('B.private()')
	def public(self):
		print('B.public()')
b=B() 
输出:
B.private()
B.public()

4.继承中的__init__

在Python中出现继承时需要注意点是:初始化函数__init__的行为:

  • 如果子类没有定义自己的初始化函数,父类的初始化会被默认调用,但是如果要实例化子类的对象,则只能传入父类的初始化函数对应的参数,要不然会出错。
#首先定义父类parent
class Parent(object):
	def __init__(self,name):
		self.name=name
		print("create an instance of:",self.__class__.name__)  #self.__class__.__name__用于显示执行该语句的类名
		print("name attribute is:",self.name)
	
#define subChild class ,继承父类:
class Child(Parent):
	pass
#子类实例化是,由于子类没有初始化,此时父类的初始化函数会被默认调用,且必须传入父类的参数那么
c=Child("init Child")
输出:
create an instance of: Child
name attribute is: init Child
  • 子类定义了自己的初始化函数,而在子类中没有显示调用父类的初始化函数,则父类的属性不会被初始化
class Parent(object):
	def __init__(self,name):
		self.name=name
		print("create an instance of: ",self.__class__.__name__)
		print("name attribute is:",self.name)
#子类继承父类
class Child(Parent):
	#子类中没有显示调用父类的初始化函数
	def __init__(self):
		print("call__init__ form Child class")
	#实例化子类
c=Child()
print(c.name)	 #将会出错,原因父类没有被初始化
  • 如果子类定义了自己的初始化函数,显示调用父类,子类和父类的属性都会被初始化
class Parent(object):
    def __init__(self, name):
        self.name = name
        print("create an instance of:", self.__class__.__name__)
        print("name attribute is:", self.name)
class Child(Parent):
	def __init__(self):
		print("call__init__form Child class")
		super(Child,self).__init__("data from Child")  #要将子类child和self传递进去
d=Parent('jhon')
c=Child()
print(c.name)
输出结果:
create an instance of: Parent
name attribute is: jhon
call__init__form Child class
create an instance of: Child
name attribute is: data from Child
data from Child

5.super的详细使用

  • super主要是用来调用父类方法来显示调用父类的,在子类中一般会定义与父类相同的属性、方法、等,从而实现子类特有的行为。也就是所,子类会继承父类的所以属性和方法,子类也可以覆盖父类同名的属性和方法:
class Parent(object):
	Value="from parent value"
	def fun(self):
		print("function is from Parent")
#定义子类,继承父类
class Child(Parent):
	Value ="from child value"
	def fun(self):
		print("funtion is from child")
		Parent.fun(self) #调用父类的fun函数方法,将self显示的传递进入
c=Child()
c.fun()
print(Child.Value)

上面继承父类的缺点:需要经过父类名硬编码到子类中,然而super方法可以解决这一问题:

class Parent(object):
   Value="from parent value"
   def fun(self):
   	print("function is from Parent")
#定义子类,继承父类
class Child(Parent):
   Value ="from child value"
   def fun(self):
   	print("funtion is from child")
   	#Parent.fun(self) #调用父类的fun函数方法,将self显示的传递进入
   	super(Child,self).fun() #和上一句相同用于调用父类方法
c=Child()
c.fun()
print(Child.Value)

输出:
funtion is from child
function is from Parent
from child value

1.参考
2.参考

你可能感兴趣的:(python学习)