def __init__(self):
pass
构造方法,可以理解为初始化方法,构造函数。主要功能:
(1)初始化一个类的属性
(2)当新成员被创建的时候,会自动调用。
class People:
def __init__(self):
print('hello world')
p = People()
class People:
def __init__(self, name, age):
print(name, ':', age)
p = People('小明', '20')
self
(1) self代表类的实例,而非类。
self代表的是类的实例。而self.__class__则指向类。
(2) self可以写成this
还是尊重常见的习惯,建议使用self
class People:
def __init__(this):
print('hello world')
p = People()
(3)方法第一个参数,必须为self,self代表的是类的实例
为什么一定要写self呢?
可以简单理解为:函数被实例调用的时候,它总得知道谁在调用吧。
class People:
def __init__(self, name, age):
# 通过下面和实例绑定
self.name = name
self.age = age
print(name, ':', age)
def eat(self):
print(self.name,'吃什么')
p = People('小明', '20')
p.eat()
类属性:公共属性,所有实例共享
实例属性:成员变量,每个实例独享
class People:
p_nation = '中国'
def __init__(self, name, age):
# 通过下面和实例绑定
self.name = name
self.age = age
print(name, ':', age)
p = People('小明', '20')
print(People.p_nation)
print(p.p_nation)
实例重新定义公共属性,其实是增加自己成员变量
class People:
p_nation = '中国'
def __init__(self, name, age):
# 通过下面和实例绑定
self.name = name
self.age = age
print(name, ':', age)
p = People('小明', '20')
p.p_nation ='美国'
print(p.p_nation) # 美国
print(People.p_nation) # 中国
继承是指将现有类的属性和行为,经过修改或重写之后,就可产生出拥有新功能的类,这样可以大幅提升程序代码的可重用性。更大的优势在于能够维持对象封装的特性。
在概念上来说:父类被称为基类,子类被称为派生类。
单继承
class Father:
name ='Father'
def work(self):
print("在家种地")
class Son(Father):
def __init__(self):
pass
son = Son()
son.work()
# 在家种地
print(son.name)
# Father
重写父类方法 和 变量
class Father:
name ='Father'
def work(self):
print("在家种地")
class Son(Father):
name = 'Son'
def work(self):
print("在上学")
son = Son()
son.work()
# 在上学
print(son.name)
# Son
除了调用原来父类的方法,还根据自己的需求扩展了子类的方法。
class Father:
def work(self):
print("在家种地")
class Son(Father):
def work(self):
Father.work(self)
print("在上学")
son = Son()
son.work()
所以,super() 函数调用父类
class Father:
name = 'Father'
def work(self,content):
print("在家种地,",content)
class Son(Father):
name = 'son'
def work(self,content):
super().work(content)
print("在上学,学习",content)
f = Father()
f.work('花生')
s = Son()
s.work('语文')
# 在家种地, 花生
# 在家种地, 语文
# 在上学,学习 语文
多继承是指派生类继承自多个基类,而这些被继承的基类相互之间可能都没有关系,简单地说,就是直接继承了两个或两个以上的基类。
class Animal:
def content(self):
print('它们都是动物')
class Horse(Animal):
def content1(self):
print('它是马')
class Donkey(Animal):
def content2(self):
print('它是驴')
class Mule(Horse, Donkey):
def content3(self):
print('它是骡子')
m = Mule()
m.content()
m.content1()
m.content2()
m.content3()
print(isinstance(m,Animal))
print(issubclass(Mule,Animal))
print(issubclass(Mule,Horse))
print(issubclass(Horse,Donkey))
它们都是动物
它是马
它是驴
它是骡子
True
True
True
False
相关函数
isinstance( 对象, 类)
判断第一个参数的对象是否属于第二个参数类的一种
issubclass(子类,父类)
如果类 1 是类 2 所指定的子类,则返回 True,否则返回 False
将数据和操作数据的方法 包装在一起 , 隐藏数据的内部细节 , 防止外界的直接访问和修改 。
封装后 , 只能通过 对外提供的接口 , 对 封装在内部的属性和方法 进行 访问和操作
成员变量 与 成员方法
class People:
p_nation = '中国'
def eat(self):
print(self.p_nation)
私有成员变量 与 私有成员方法
私有成员变量 : 以 双下划线 开头 __私有成员变量名
私有成员方法 : 以 双下划线 开头 __私有成员方法名
class People:
__name = '小明'
def say(self):
# 只能在内部掉用
self.__name = '大明'
self.__say()
print(self.__name)
def __say(self):
self.__name = '__大明'
print('say chinese')
p = People()
p.say()
###########
say chinese
__大明
Python是弱类型语言,其最明显的特征是在使用变量时,无需为其指定具体的数据类型。这会导致一种情况,即同一变量可能会被先后赋值不同的类对象。
类的多态特性,还要满足以下 2 个前提条件:
(1)继承:多态一定是发生在子类和父类之间;
(2)重写:子类重写了父类的方法。
class People:
def hello(self):
print('hello people')
class Men(People):
def hello(self):
print('hello man')
class Women(People):
def hello(self):
print('hello woman')
class Test:
def hello(self, arg):
arg.hello()
p = People()
men = Men()
women = Women()
test = Test()
test.hello(p)
test.hello(men)
test.hello(women)
#######
hello people
hello man
hello woman
类的实例方法:在类的内部,使用 def 关键字可以为类定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数。
类的实例私有方法:__private_method:两个下划线开头,声明该方法为私有方法,不能在类的外部调用。在类的内部调用 self.__private_methods 。
class People:
name = '小明'
__name = '__小明'
def say(self):
# 只能在内部掉用
self.__name = '大明'
self.__say()
print(self.__name)
def __say(self):
self.__name = '__大明'
print('say chinese')
p = People()
p.say()
###########
say chinese
__大明
类的方法: 无需实例化,可以通过类直接调用的方法,但是方法的第一个参数接收的一定是类本身。
使用类方法不需要定义一个实例,类方法中的cls指向类,不像实例方法中的self指向一个实例。定义类方法,需要在函数前添加@classmethod
class People:
__name = '小明'
@classmethod
def hello(cls):
print(cls.__name)
People.hello()
静态方法
一般用于和类对象以及实例对象无关的代码。也就是意思不能访问类变量,也不能访问实例变量。
class People:
@staticmethod
def hello_word():
print('hello world')
People.hello_word()
属性方法(@property)
使用@property装饰器来创建只读属性,@property装饰器会将方法转换为相同名称的只读属性,可以与所定义的属性配合使用,这样可以防止属性被修改。
加了@property后,可以用调用属性的形式来调用方法,后面不需要加()。
class People:
@property
def hello_1(self):
return 'hello'
@property
def hello_2(self):
return self.__name
p = People()
print(p.hello_1)
print(p.hello_2)
户进行属性调用的时候,直接调用hello_2即可,而不用知道属性名_name,因此用户无法更改属性,从而保护了类的属性。
python的反射机制,核心就是利用字符串去已存在的模块中找到指定的属性或方法,找到方法后自动执行(基于字符串的事件驱动)。
一般使用场景:动态的向对象中添加属性和方法;也可以动态的调用对象中的方法或者属性。
判断输入的name_str字符串在对象obj中是否存在(属性或方法),存在返回True,否则返回False。
class People():
nation = 'CN'
def __init__(self,name,age):
self.name = name
self.age = age
def get_name(self):
print(self.name)
p = People('小明',18)
print(hasattr(People, 'nation'))
print(hasattr(p, 'age'))
print(hasattr(People, 'get_name'))
print(hasattr(People, 'xxxxxx'))
True
True
True
False
将按照输入的name_str字符串在对象obj中查找,如找到同名属性,则返回该属性;如找到同名方法,则返回方法的引用;如果未能找到同名的属性或者方法。
class People():
nation = 'CN'
def __init__(self,name,age):
self.name = name
self.age = age
def get_name(self):
print(self.name)
p = People('小明',18)
# 反射获取类变量
print(getattr(People, 'nation'))
# 反射获取成员变量
print(getattr(p, 'name'))
# 反射获取成员方法,返回方法是一个引用地址,要想执行该方法,需要在后面加上小括号
getattr(p, 'get_name')()
#########
CN
小明
小明
name_str为属性名或者方法名,value为属性值或者方法的引用。
class People():
nation = 'CN'
def __init__(self,name,age):
self.name = name
self.age = age
def get_name(self):
print(self.name)
p = People('小明',18)
setattr(p, 'name','小小明')
print(getattr(p,'name'))
setattr(p,'new_get_name',p.get_name)
getattr(p, 'new_get_name')()
##################
小小明
小小明
将你输入的字符串name_str在对象obj中查找,如找到同名属性或者方法就进行删除。
删除属性和方法之后,再次调用就会报AttributeError错误
class People():
nation = 'CN'
def __init__(self,name,age):
self.name = name
self.age = age
def get_name(self):
print(self.name)
p = People('小明',18)
delattr(p,'name')
getattr(p,'name')
delattr(p,'new_get_name')
getattr(p, 'new_get_name')()
#######
AttributeError: 'People' object has no attribute 'name'