定义一个类:
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))
和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。
成员变量访问权限控制:
如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__
,在Python中,实例的变量名如果以__
开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。
class Student(object):
def print_score(self):
print('score is: %s' % self.score)
def __init__(self,name,age):
self.__name = name
self.__age = age
ddd = Student('kk',25)
print(ddd.__name)
Traceback (most recent call last):
File "./ssss.py", line 113, in <module>
print(ddd.__name)
AttributeError: 'Student' object has no attribute '__name'
如需访问内部变量,则通过写getter与setter
获取对象信息:
1.基本类型都可以用 type()
type('abc')==type('123')
type(abs)==types.BuiltinFunctionType
2.对于class的继承关系来说,使用type()就很不方便。我们要判断class的类型,可以使用isinstance()函数。
object -> Animal -> Dog -> Husky
a = Animal()
d = Dog()
h = Husky()
isinstance(h, Dog)
True
isinstance(d, Husky)
False
- 如果要获得一个对象的所有属性和方法,可以使用dir(),函数它返回一个包含字符串的list。
class MyObject(object):
def __init__(self):
self.x = 9
def power(self):
return self.x * self.x
obj = MyObject()
hasattr(obj, 'y') # 有属性'y'吗?
False
setattr(obj, 'y', 19) # 设置一个属性'y'
hasattr(obj, 'y') # 有属性'y'吗?
True
getattr(obj, 'y') # 获取属性'y'
19
类属性:
class Student(object):
name = 'Student'
这样所有的Student实例都有name这个属性,但一旦通过实例绑定同名的属性,就会被覆盖;
s.name = 'Michael' # 给实例绑定name属性
print(s.name) # 由于实例属性优先级比类属性高,因此,它会屏蔽掉类的name属性
Michael
使用slots限定实例能添加的属性:
由于python是一种动态语言,所以我们可以动态为一个类添加属性和方法:
添加属性:
class Forg(object):
pass
forg = Forg()
forg.legCount = 4
print(forg.legCount)
添加方法:
def set_eyes(self,eyeCount):
self.eyeCount = eyeCount
from types import MethodType
forg.set_eyes = MethodType(set_eyes,forg)
forg.set_eyes(2)
print(forg.eyeCount)
以上这种添加方法的方式只能当前这个实例用,若要类的所有实例都能用,可以给class绑定方法:
Forg.set_eyes = set_eyes
现在我们想限制类添加的属性:
Python允许在定义class的时候,定义一个特殊的__slots__
变量,来限制该class实例能添加的属性:
class PinkPig(object):
__slots__ = ('skinColor','hairStyle')
liPig = PinkPig()
liPig.skinColor = 'pink'
print(liPig.skinColor)
liPig.age = '3'
print(liPig.age)
#结果:
pink
Traceback (most recent call last):
File "./ssss.py", line 150, in <module>
liPig.age = '3'
AttributeError: 'PinkPig' object has no attribute 'age'
继承,子类定义的__slots__
会与父类合并作为子类的限制。
@property:
为了绑定的属性数据安全性,保证封装,一般都会给属性写setter与getter,而不是直接修改。
@property装饰器就是负责把一个方法变成属性调用。
class PinkPig(object):
__slots__ = ('skinColor','hairStyle','_noselen')
@property
def noselen(self):
return self._noselen
@noselen.setter
def noselen(self,value):
if not isinstance(value,int):
raise ValueError('lenght must be an integer')
if value < 0 or value > 100:
raise ValueError('length must be reasonable')
self._noselen = value
liPig = PinkPig()
liPig.noselen = 95
print(liPig.noselen)
通过该装饰器,可以控制读写操作权限。只给setter就只能写,只给getter就只能读。
python支持多继承
不过主继承只有一个,为了扩展功能,继承其他的功能类,列如ThreadingMixIn
。这种方式有点类似于swift中的protocol,Equatable
这样的协议。
定制类:
其实就是自定义打印信息,默认的打印一个object是
<__main__.Student object at 0x109afb190>
如果我们重写实现__str__
方法,就会打印我们自定义的字符串
class Stu(object):
def __str__(self):
return '这货是个类你信吗?反正我信了!'
mim = Stu()
print(mim)
这货是个类你信吗?反正我信了!
枚举类:
from enum import Enum,unique
Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))
@unique
class Weekday(Enum):
Sun = 0
Mon = 1
Tue = 2
Wed = 3
Thu = 4
Fri = 5
Sat = 6
print(Weekday.Mon)
@unique
装饰器可以帮助我们检查保证没有重复值。
关于元类:
type()
函数可以查看一个类型或变量的类型。
class的定义是运行时动态创建的,而创建class的方法就是使用type()函数。
type()
函数既可以返回一个对象的类型,又可以创建出新的类型
def fn(self, name='world'): # 先定义函数
print('Hello, %s.' % name)
Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class
</code></pre><p>要创建一个class对象,<code>type()</code>函数依次传入3个参数:</p><ol><li>class的名称;</li><li>继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法;</li><li>class的方法名称与函数绑定,这里我们把函数<code>fn</code>绑定到方法名<code>hello</code>上。</li></ol>
除了使用<code>type()</code>函数之外,还可以使用metaclass来创建类
# metaclass是类的模板,所以必须从`type`类型派生:
class ListMetaclass(type):
def __new__(cls, name, bases, attrs):
attrs['add'] = lambda self, value: self.append(value)
return type.__new__(cls, name, bases, attrs)
class MyList(list,metaclass = ListMetaclass):
pass
l = MyList()
l.add(1)
print(l)
__new__
()方法接收到的参数依次是:
1.当前准备创建的类的对象;
2.类的名字;
3.类继承的父类集合;
4.类的方法集合。
网友评论