day07面向對象(初級篇)

Python 面向對象(初級篇)

本章內容簡介:

1. 模塊(溫習,主要是練習幾個實例): html

  1)解析配置模塊configparser;node

  2)解析xml模塊;python

  3)文件壓縮模塊zipfile和tarfile;  編程

2. 面向對象(初級篇)app

一. 模塊

2.1) 解析配置模塊:configparser

configparser用於處理特定格式的文件,其本質上是利用open來操做文件。dom

實例:ide

  • text文件,文件格式:
[section1] # 節點
k1 = v1    # 值
k2:v2       # 值
 
[section2] # 節點
k1 = v1    # 值
  •  1.  以列表的形式獲取全部節點名:
import configparser

config = configparser.ConfigParser()
config.read('text',encoding='utf-8')
print(config)
ret = config.sections()
print(ret)

執行結果:函數

<configparser.ConfigParser object at 0x000000000114E860>
['section1', 'section2']

代碼解析:
加載模塊後,ConfigParser類( implementing interpolation)執行插入; read讀取文件或是列表文件,可選字符集(獲得的結果是一個內存地址);oop

sections解釋:Return a list of section names(全文檢索返回節點名字的列表)ui

  • 2.  獲取指定節點下全部的鍵值對
import configparser

config = configparser.ConfigParser()
config.read('text',encoding='utf-8')
ret = config.items('section1')
print(ret)

執行結果:

[('k1', 'v1'), ('k2', 'v2')]

代碼解析:

  items(‘節點名’),源碼解釋Return a list of (name, value) tuples for each option in a section。返回這個節點的key、value爲元組的列表;

  • 3. 獲取指定節點下指定key的值
import configparser

config = configparser.ConfigParser()
config.read('text',encoding='utf-8')
v1 = config.get('section1', 'k1')
v2 = config.get('section1', 'k2')
print(v1,v2)

執行結果:

v1 v2

代碼解析:

  get(「節點名」,「key值」),獲取節點下key值對應的value,若是輸入的key值不存在,會報錯;

  • 4. 獲取指定節點下的鍵值
import configparser

config = configparser.ConfigParser()
config.read('text',encoding='utf-8')
ret = config.options('section1')
print(ret)

執行結果:  ['k1', 'k2']

代碼解析:

  options(self, section) : Return a list of option names for the given section name.

  • 5. 檢查、添加、刪除節點
import configparser

config = configparser.ConfigParser()
config.read('text',encoding='utf-8')
has_sec = config.has_section('section1')
print(has_sec)

執行結果:  True

代碼解析:

  has_section(self, section)檢查: Indicate whether the named section is present in the configuration.  The DEFAULT section is not acknowledged.

  指明 兩個中的一個:這個節點名在當前的配置裏(返回True),這個默認的節點是不被認可的(返回False)。

添加和刪除

# 添加一個節點
import configparser

config = configparser.ConfigParser()
config.read('text',encoding='utf-8')
config.add_set('section3')
config.write(open('text', 'w'))

# 設置節點裏的內容
config.set('section3','k1','v1')
config.write(open('text', 'w'))

# 刪除節點
config.remove_section('section3')
config.write(open('text', 'w'))
  • 6. 檢查、刪除、設置指定組內的鍵值對
import configparser

config = configparser.ConfigParser()
config.read('text',encoding='utf-8')

# 檢查section1節點裏是否存在k1這個名字;
has_opt = config.has_option('section1', 'k1')
print(has_opt)

# 刪除section1節點裏是 k1的內容;
config.remove_option('section1', 'k1')
config.write(open('text', 'w'))

# section1節點裏設置一個值
config.set('section1', 'k10', "123")
config.write(open('text', 'w'))

總結:

  當增、刪、改文件的時候,要將改變寫入文件; 

2.2)解析xml模塊:xml

 XML是實現不一樣語言或程序之間進行數據交換的協議,XML文件格式以下:

<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2023</year>
        <gdppc>141100</gdppc>
        <neighbor direction="E" name="Austria" />
        <neighbor direction="W" name="Switzerland" />
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2026</year>
        <gdppc>59900</gdppc>
        <neighbor direction="N" name="Malaysia" />
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2026</year>
        <gdppc>13600</gdppc>
        <neighbor direction="W" name="Costa Rica" />
        <neighbor direction="E" name="Colombia" />
    </country>
</data>

一、解析XML

利用ElementTree.XML將字符串解析成xml對象

from xml.etree import ElementTree as ET


# 打開文件,讀取XML內容
str_xml = open('xo.xml', 'r').read()

# 將字符串解析成xml特殊對象,root代指xml文件的根節點
root = ET.XML(str_xml)

獲取的根節點data:  <Element 'data' at 0x00000000006E72C8>

利用ElementTree.parse將文件直接解析成xml對象

from xml.etree import ElementTree as ET

# 直接解析xml文件
tree = ET.parse("xo.xml")

# 獲取xml文件的根節點
root = tree.getroot()

獲取的根節點data:  <Element 'data' at 0x00000000006E72C8>

二、操做XML

XML格式類型是節點嵌套節點,對於每個節點均有如下功能,以便對當前節點進行操做:

節點功能一覽表

class Element:
    """An XML element.

    This class is the reference implementation of the Element interface.

    An element's length is its number of subelements.  That means if you
    want to check if an element is truly empty, you should check BOTH
    its length AND its text attribute.

    The element tag, attribute names, and attribute values can be either
    bytes or strings.

    *tag* is the element name.  *attrib* is an optional dictionary containing
    element attributes. *extra* are additional element attributes given as
    keyword arguments.

    Example form:
        <tag attrib>text<child/>...</tag>tail

    """

    當前節點的標籤名
    tag = None
    """The element's name."""

    當前節點的屬性

    attrib = None
    """Dictionary of the element's attributes."""

    當前節點的內容
    text = None
    """
    Text before first subelement. This is either a string or the value None.
    Note that if there is no text, this attribute may be either
    None or the empty string, depending on the parser.

    """

    tail = None
    """
    Text after this element's end tag, but before the next sibling element's
    start tag.  This is either a string or the value None.  Note that if there
    was no text, this attribute may be either None or an empty string,
    depending on the parser.

    """

    def __init__(self, tag, attrib={}, **extra):
        if not isinstance(attrib, dict):
            raise TypeError("attrib must be dict, not %s" % (
                attrib.__class__.__name__,))
        attrib = attrib.copy()
        attrib.update(extra)
        self.tag = tag
        self.attrib = attrib
        self._children = []

    def __repr__(self):
        return "<%s %r at %#x>" % (self.__class__.__name__, self.tag, id(self))

    def makeelement(self, tag, attrib):
        建立一個新節點
        """Create a new element with the same type.

        *tag* is a string containing the element name.
        *attrib* is a dictionary containing the element attributes.

        Do not call this method, use the SubElement factory function instead.

        """
        return self.__class__(tag, attrib)

    def copy(self):
        """Return copy of current element.

        This creates a shallow copy. Subelements will be shared with the
        original tree.

        """
        elem = self.makeelement(self.tag, self.attrib)
        elem.text = self.text
        elem.tail = self.tail
        elem[:] = self
        return elem

    def __len__(self):
        return len(self._children)

    def __bool__(self):
        warnings.warn(
            "The behavior of this method will change in future versions.  "
            "Use specific 'len(elem)' or 'elem is not None' test instead.",
            FutureWarning, stacklevel=2
            )
        return len(self._children) != 0 # emulate old behaviour, for now

    def __getitem__(self, index):
        return self._children[index]

    def __setitem__(self, index, element):
        # if isinstance(index, slice):
        #     for elt in element:
        #         assert iselement(elt)
        # else:
        #     assert iselement(element)
        self._children[index] = element

    def __delitem__(self, index):
        del self._children[index]

    def append(self, subelement):
        爲當前節點追加一個子節點
        """Add *subelement* to the end of this element.

        The new element will appear in document order after the last existing
        subelement (or directly after the text, if it's the first subelement),
        but before the end tag for this element.

        """
        self._assert_is_element(subelement)
        self._children.append(subelement)

    def extend(self, elements):
        爲當前節點擴展 n 個子節點
        """Append subelements from a sequence.

        *elements* is a sequence with zero or more elements.

        """
        for element in elements:
            self._assert_is_element(element)
        self._children.extend(elements)

    def insert(self, index, subelement):
        在當前節點的子節點中插入某個節點,即:爲當前節點建立子節點,而後插入指定位置
        """Insert *subelement* at position *index*."""
        self._assert_is_element(subelement)
        self._children.insert(index, subelement)

    def _assert_is_element(self, e):
        # Need to refer to the actual Python implementation, not the
        # shadowing C implementation.
        if not isinstance(e, _Element_Py):
            raise TypeError('expected an Element, not %s' % type(e).__name__)

    def remove(self, subelement):
        在當前節點在子節點中刪除某個節點
        """Remove matching subelement.

        Unlike the find methods, this method compares elements based on
        identity, NOT ON tag value or contents.  To remove subelements by
        other means, the easiest way is to use a list comprehension to
        select what elements to keep, and then use slice assignment to update
        the parent element.

        ValueError is raised if a matching element could not be found.

        """
        # assert iselement(element)
        self._children.remove(subelement)

    def getchildren(self):
        獲取全部的子節點(廢棄)
        """(Deprecated) Return all subelements.

        Elements are returned in document order.

        """
        warnings.warn(
            "This method will be removed in future versions.  "
            "Use 'list(elem)' or iteration over elem instead.",
            DeprecationWarning, stacklevel=2
            )
        return self._children

    def find(self, path, namespaces=None):
        獲取第一個尋找到的子節點
        """Find first matching element by tag name or path.

        *path* is a string having either an element tag or an XPath,
        *namespaces* is an optional mapping from namespace prefix to full name.

        Return the first matching element, or None if no element was found.

        """
        return ElementPath.find(self, path, namespaces)

    def findtext(self, path, default=None, namespaces=None):
        獲取第一個尋找到的子節點的內容
        """Find text for first matching element by tag name or path.

        *path* is a string having either an element tag or an XPath,
        *default* is the value to return if the element was not found,
        *namespaces* is an optional mapping from namespace prefix to full name.

        Return text content of first matching element, or default value if
        none was found.  Note that if an element is found having no text
        content, the empty string is returned.

        """
        return ElementPath.findtext(self, path, default, namespaces)

    def findall(self, path, namespaces=None):
        獲取全部的子節點
        """Find all matching subelements by tag name or path.

        *path* is a string having either an element tag or an XPath,
        *namespaces* is an optional mapping from namespace prefix to full name.

        Returns list containing all matching elements in document order.

        """
        return ElementPath.findall(self, path, namespaces)

    def iterfind(self, path, namespaces=None):
        獲取全部指定的節點,並建立一個迭代器(能夠被for循環)
        """Find all matching subelements by tag name or path.

        *path* is a string having either an element tag or an XPath,
        *namespaces* is an optional mapping from namespace prefix to full name.

        Return an iterable yielding all matching elements in document order.

        """
        return ElementPath.iterfind(self, path, namespaces)

    def clear(self):
        清空節點
        """Reset element.

        This function removes all subelements, clears all attributes, and sets
        the text and tail attributes to None.

        """
        self.attrib.clear()
        self._children = []
        self.text = self.tail = None

    def get(self, key, default=None):
        獲取當前節點的屬性值
        """Get element attribute.

        Equivalent to attrib.get, but some implementations may handle this a
        bit more efficiently.  *key* is what attribute to look for, and
        *default* is what to return if the attribute was not found.

        Returns a string containing the attribute value, or the default if
        attribute was not found.

        """
        return self.attrib.get(key, default)

    def set(self, key, value):
        爲當前節點設置屬性值
        """Set element attribute.

        Equivalent to attrib[key] = value, but some implementations may handle
        this a bit more efficiently.  *key* is what attribute to set, and
        *value* is the attribute value to set it to.

        """
        self.attrib[key] = value

    def keys(self):
        獲取當前節點的全部屬性的 key

        """Get list of attribute names.

        Names are returned in an arbitrary order, just like an ordinary
        Python dict.  Equivalent to attrib.keys()

        """
        return self.attrib.keys()

    def items(self):
        獲取當前節點的全部屬性值,每一個屬性都是一個鍵值對
        """Get element attributes as a sequence.

        The attributes are returned in arbitrary order.  Equivalent to
        attrib.items().

        Return a list of (name, value) tuples.

        """
        return self.attrib.items()

    def iter(self, tag=None):
        在當前節點的子孫中根據節點名稱尋找全部指定的節點,並返回一個迭代器(能夠被for循環)。
        """Create tree iterator.

        The iterator loops over the element and all subelements in document
        order, returning all elements with a matching tag.

        If the tree structure is modified during iteration, new or removed
        elements may or may not be included.  To get a stable set, use the
        list() function on the iterator, and loop over the resulting list.

        *tag* is what tags to look for (default is to return all elements)

        Return an iterator containing all the matching elements.

        """
        if tag == "*":
            tag = None
        if tag is None or self.tag == tag:
            yield self
        for e in self._children:
            yield from e.iter(tag)

    # compatibility
    def getiterator(self, tag=None):
        # Change for a DeprecationWarning in 1.4
        warnings.warn(
            "This method will be removed in future versions.  "
            "Use 'elem.iter()' or 'list(elem.iter())' instead.",
            PendingDeprecationWarning, stacklevel=2
        )
        return list(self.iter(tag))

    def itertext(self):
        在當前節點的子孫中根據節點名稱尋找全部指定的節點的內容,並返回一個迭代器(能夠被for循環)。
        """Create text iterator.

        The iterator loops over the element and all subelements in document
        order, returning all inner text.

        """
        tag = self.tag
        if not isinstance(tag, str) and tag is not None:
            return
        if self.text:
            yield self.text
        for e in self:
            yield from e.itertext()
            if e.tail:
                yield e.tail

因爲 每一個節點 都具備以上的方法,而且在上一步驟中解析時均獲得了root(xml文件的根節點),so   能夠利用以上方法進行操做xml文件。

a. 遍歷XML文檔的全部內容

from xml.etree import ElementTree as ET

# 直接解析xml文件
tree = ET.parse("xo.xml")

# 獲取xml文件的根節點
root = tree.getroot()

### 操做

# 頂層標籤
print(root.tag)

# 遍歷XML文檔的第二層
for child in root:
    # 第二層節點的標籤名稱和標籤屬性
    print(child.tag, child.attrib)
    # 遍歷XML文檔的第三層
    for i in child:
        # 第二層節點的標籤名稱和內容
        print(i.tag,i.text)

執行結果:

data
country {'name': 'Liechtenstein'}
rank 2
year 2023
gdppc 141100
neighbor None
neighbor None
country {'name': 'Singapore'}
rank 5
year 2026
gdppc 59900
neighbor None
country {'name': 'Panama'}
rank 69
year 2026
gdppc 13600
neighbor None
neighbor None

b、遍歷XML中指定的節點

from xml.etree import ElementTree as ET

# 直接解析xml文件
tree = ET.parse("xo.xml")
# 獲取xml文件的根節點
root = tree.getroot()

### 操做
# 頂層標籤
print(root.tag)
# 遍歷XML中全部的year節點
for node in root.iter('year'):
    # 節點的標籤名稱和內容
    print(node.tag, node.text)

執行結果:

data
year 2023
year 2026
year 2026

c、修改節點內容

因爲修改的節點時,均是在內存中進行,其不會影響文件中的內容。因此,若是想要修改,則須要從新將內存中的內容寫到文件。

  • 方法一,解析字符串方式,修改,保存:
from xml.etree import ElementTree as ET

# 打開文件,讀取XML內容
str_xml = open('xo.xml', 'r').read()
# 將字符串解析成xml特殊對象,root代指xml文件的根節點
root = ET.XML(str_xml)
############ 操做 ############
# 頂層標籤
print(root.tag)
# 循環全部的year節點
for node in root.iter('year'):
    # 將year節點中的內容自增一
    new_year = int(node.text) + 1
    node.text = str(new_year)
    # 設置屬性
    node.set('name', 'alex')
    node.set('age', '18')
    # 刪除屬性
    del node.attrib['name']
############ 保存文件 ############
tree = ET.ElementTree(root)
tree.write("newnew.xml", encoding='utf-8')

執行結果:

  打印輸出一個data(根節點),將改過的文件另存爲 newnew.xml。

  • 方法二,解析文件方式,修改,保存:
from xml.etree import ElementTree as ET

############ 解析方式二 ############

# 直接解析xml文件
tree = ET.parse("xo.xml")
# 獲取xml文件的根節點
root = tree.getroot()
############ 操做 ############
# 頂層標籤
print(root.tag)

# 循環全部的year節點
for node in root.iter('year'):
    # 將year節點中的內容自增一
    new_year = int(node.text) + 1
    node.text = str(new_year)

    # 設置屬性
    node.set('name', 'alex')
    node.set('age', '18')
    # 刪除屬性
    del node.attrib['name']

############ 保存文件 ############
tree.write("newnew.xml", encoding='utf-8')

d、刪除節點

方法一,解析字符串方式打開,刪除,保存:

from xml.etree import ElementTree as ET

############ 解析字符串方式打開 ############

# 打開文件,讀取XML內容
str_xml = open('xo.xml', 'r').read()

# 將字符串解析成xml特殊對象,root代指xml文件的根節點
root = ET.XML(str_xml)

############ 操做 ############

# 頂層標籤
print(root.tag)

# 遍歷data下的全部country節點
for country in root.findall('country'):
    # 獲取每個country節點下rank節點的內容
    rank = int(country.find('rank').text)

    if rank > 50:
        # 刪除指定country節點
        root.remove(country)

############ 保存文件 ############
tree = ET.ElementTree(root)
tree.write("newnew.xml", encoding='utf-8')

方法二,解析文件方式打開,刪除,保存:

from xml.etree import ElementTree as ET

############ 解析文件方式 ############

# 直接解析xml文件
tree = ET.parse("xo.xml")

# 獲取xml文件的根節點
root = tree.getroot()

############ 操做 ############

# 頂層標籤
print(root.tag)

# 遍歷data下的全部country節點
for country in root.findall('country'):
    # 獲取每個country節點下rank節點的內容
    rank = int(country.find('rank').text)

    if rank > 50:
        # 刪除指定country節點
        root.remove(country)

############ 保存文件 ############
tree.write("newnew.xml", encoding='utf-8')

三、建立XML文檔

方法一:

from xml.etree import ElementTree as ET


# 建立根節點
root = ET.Element("famliy")


# 建立節點大兒子
son1 = ET.Element('son', {'name': '兒1'})
# 建立小兒子
son2 = ET.Element('son', {"name": '兒2'})

# 在大兒子中建立兩個孫子
grandson1 = ET.Element('grandson', {'name': '兒11'})
grandson2 = ET.Element('grandson', {'name': '兒12'})
son1.append(grandson1)
son1.append(grandson2)


# 把兒子添加到根節點中
root.append(son1)
root.append(son1)

tree = ET.ElementTree(root)
tree.write('oooo.xml',encoding='utf-8', short_empty_elements=False)

方法二:

from xml.etree import ElementTree as ET

# 建立根節點
root = ET.Element("famliy")


# 建立大兒子
# son1 = ET.Element('son', {'name': '兒1'})
son1 = root.makeelement('son', {'name': '兒1'})
# 建立小兒子
# son2 = ET.Element('son', {"name": '兒2'})
son2 = root.makeelement('son', {"name": '兒2'})

# 在大兒子中建立兩個孫子
# grandson1 = ET.Element('grandson', {'name': '兒11'})
grandson1 = son1.makeelement('grandson', {'name': '兒11'})
# grandson2 = ET.Element('grandson', {'name': '兒12'})
grandson2 = son1.makeelement('grandson', {'name': '兒12'})

son1.append(grandson1)
son1.append(grandson2)


# 把兒子添加到根節點中
root.append(son1)
root.append(son1)

tree = ET.ElementTree(root)
tree.write('oooo.xml',encoding='utf-8', short_empty_elements=False)

方法三:

from xml.etree import ElementTree as ET


# 建立根節點
root = ET.Element("famliy")


# 建立節點大兒子
son1 = ET.SubElement(root, "son", attrib={'name': '兒1'})
# 建立小兒子
son2 = ET.SubElement(root, "son", attrib={"name": "兒2"})

# 在大兒子中建立一個孫子
grandson1 = ET.SubElement(son1, "age", attrib={'name': '兒11'})
grandson1.text = '孫子'


et = ET.ElementTree(root)  #生成文檔對象
et.write("test.xml", encoding="utf-8", xml_declaration=True, short_empty_elements=False)

因爲原生保存的XML時默認無縮進,若是想要設置縮進的話, 須要修改保存方式:

from xml.etree import ElementTree as ET
from xml.dom import minidom


def prettify(elem):
    """將節點轉換成字符串,並添加縮進。
    """
    rough_string = ET.tostring(elem, 'utf-8')
    reparsed = minidom.parseString(rough_string)
    return reparsed.toprettyxml(indent="\t")

# 建立根節點
root = ET.Element("famliy")


# 建立大兒子
# son1 = ET.Element('son', {'name': '兒1'})
son1 = root.makeelement('son', {'name': '兒1'})
# 建立小兒子
# son2 = ET.Element('son', {"name": '兒2'})
son2 = root.makeelement('son', {"name": '兒2'})

# 在大兒子中建立兩個孫子
# grandson1 = ET.Element('grandson', {'name': '兒11'})
grandson1 = son1.makeelement('grandson', {'name': '兒11'})
# grandson2 = ET.Element('grandson', {'name': '兒12'})
grandson2 = son1.makeelement('grandson', {'name': '兒12'})

son1.append(grandson1)
son1.append(grandson2)


# 把兒子添加到根節點中
root.append(son1)
root.append(son1)


raw_str = prettify(root)

f = open("xxxoo.xml",'w',encoding='utf-8')
f.write(raw_str)
f.close()

2.3)文件壓縮模塊:(tarfile 和 zipfile)

 tarfile模塊使用:

import tarfile

tar = tarfile.open('your.tar','w')
tar.add('test1.py',arcname='a.py')
tar.add('text',arcname='text123')
tar.close()

代碼解析:

  tarfile壓縮,首先要用open建立一個壓縮文件,w只寫;而後使用add將文件添加到壓縮文件裏,還可使用arcname從新命名;最後close關閉文件;

解壓tarfile:

tar = tarfile.open('your.tar','r')
tar.extractall()  # 所有解壓

obj = tar.getmember('a.py')
tar.extract(obj)  #解壓指定文件
tar.close()

代碼解析:

  tarfile解壓縮,首先要用open打開一個壓縮文件,r只讀;而後使用extractall所有解壓,或是使用getmember獲取元素,使用extract解壓獲取的指定文件;最後close關閉文件;

zipfile模塊使用:

import zipfile

# 壓縮
z = zipfile.ZipFile('laxi.zip', 'w')
z.write('a.log') #每次寫入一個文件,多個只會寫入最後一個;
z.write('data.data')
z.close()

z = zipfile.ZipFile('laxi.zip', 'a')
z.write('data.data')# 若是文件已存在,仍然繼續寫入副本,打印警告信息;
z.close()

解壓縮:

import zipfile

# 解壓縮
z = zipfile.ZipFile('laxi.zip', 'r')
z.extractall()# 解壓所有;
z.close()

# 查當作員
li = z.namelist()
z.close()
print(li) #成員將以列表的形式顯示

#解壓指定成員;
obj = z.getinfo('text') #獲取指定成員
z.extract(obj) # 解壓
z.close()

二. 面向對象(初級篇)

簡述Python編程的三種形式:

  • 面向過程:根據業務邏輯從上到下寫壘代碼
  • 函數式:將某功能代碼封裝到函數中,往後便無需重複編寫,僅調用函數便可
  • 面向對象:對函數進行分類和封裝,讓開發「更快更好更強...「

面向對象編程(Object Oriented Programming,OOP,面向對象程序設計);

簡單來講,面向對象編程就是使用class建立一個類,類裏建立一些方法(每一個方法是一個函數),建立類的對象,對象來調用類裏的方法,執行;

面向對象三大特性

面向對象的三大特性是指:封裝、繼承和多態。

1、封裝

封裝,顧名思義就是將內容封裝到某個地方,之後再去調用被封裝在某處的內容。

因此,在使用面向對象的封裝特性時,須要:

  • 將內容封裝到某處
  • 從某處調用被封裝的內容

第一步:將內容封裝到某處

對象的參數被封裝到對象裏,對象自己帶人到init函數的self中使用,self == obj1,self是一個形式參數等於對象自己;

因此,內容其實被封裝到了對象 obj1 和 obj2 中,每一個對象中都有 name 和 age 屬性。

第二步:從某處調用被封裝的內容

調用被封裝的內容時,有兩種狀況:

  • 經過對象直接調用
  • 經過self間接調用

對於面向對象的封裝來講,其實就是使用構造方法將內容封裝到 對象 中,而後經過對象直接或者self間接獲取被封裝的內容。

2、繼承

繼承,面向對象中的繼承和現實生活中的繼承相同,即:子能夠繼承父的內容。

例如:

動物:吃、喝、拉、撒

     貓:喵喵叫(貓繼承動物的功能)

     狗:汪汪叫(狗繼承動物的功能)

class 動物:

    def 吃(self):
        # do something

    def 喝(self):
        # do something

    def 拉(self):
        # do something

    def 撒(self):
        # do something

# 在類後面括號中寫入另一個類名,表示當前類繼承另一個類
class 貓(動物):

    def 喵喵叫(self):
        print '喵喵叫'
        
# 在類後面括號中寫入另一個類名,表示當前類繼承另一個類
class 狗(動物):

    def 汪汪叫(self):
        print '汪汪叫'

因此,對於面向對象的繼承來講,其實就是將多個類共有的方法提取到父類中,子類僅需繼承父類而沒必要一一實現每一個方法。

注:除了子類和父類的稱謂,你可能看到過 派生類 和 基類 ,他們與子類和父類只是叫法不一樣而已。

Python能夠多繼承,什麼是多繼承?

一、Python的類能夠繼承多個類,Java和C#中則只能繼承一個類

二、Python的類若是繼承了多個類,那麼其尋找方法的方式有兩種,分別是:深度優先廣度優先

  • 當類是經典類時,多繼承狀況下,會按照深度優先方式查找
  • 當類是新式類時,多繼承狀況下,會按照廣度優先方式查找

經典類和新式類,從字面上能夠看出一個老一個新,新的必然包含了跟多的功能,也是以後推薦的寫法,從寫法上區分的話,若是 當前類或者父類繼承了object類,那麼該類即是新式類,不然即是經典類。

  • 經典類多繼承
class D:

    def bar(self):
        print 'D.bar'


class C(D):

    def bar(self):
        print 'C.bar'


class B(D):

    def bar(self):
        print 'B.bar'


class A(B, C):

    def bar(self):
        print 'A.bar'

a = A()
# 執行bar方法時
# 首先去A類中查找,若是A類中沒有,則繼續去B類中找,若是B類中麼有,則繼續去D類中找,若是D類中麼有,則繼續去C類中找,若是仍是未找到,則報錯
# 因此,查找順序:A --> B --> D --> C
# 在上述查找bar方法的過程當中,一旦找到,則尋找過程當即中斷,便不會再繼續找了
a.bar()
  • 新式類多繼承
class D(object):

    def bar(self):
        print 'D.bar'


class C(D):

    def bar(self):
        print 'C.bar'


class B(D):

    def bar(self):
        print 'B.bar'


class A(B, C):

    def bar(self):
        print 'A.bar'

a = A()
# 執行bar方法時
# 首先去A類中查找,若是A類中沒有,則繼續去B類中找,若是B類中麼有,則繼續去C類中找,若是C類中麼有,則繼續去D類中找,若是仍是未找到,則報錯
# 因此,查找順序:A --> B --> C --> D
# 在上述查找bar方法的過程當中,一旦找到,則尋找過程當即中斷,便不會再繼續找了
a.bar()

經典類:首先去A類中查找,若是A類中沒有,則繼續去B類中找,若是B類中麼有,則繼續去D類中找,若是D類中麼有,則繼續去C類中找,若是仍是未找到,則報錯

新式類:首先去A類中查找,若是A類中沒有,則繼續去B類中找,若是B類中麼有,則繼續去C類中找,若是C類中麼有,則繼續去D類中找,若是仍是未找到,則報錯

注意:在上述查找過程當中,一旦找到,則尋找過程當即中斷,便不會再繼續找了

3、多態 

 Pyhon不支持多態而且也用不到多態,多態的概念是應用於Java和C#這一類強類型語言中,而Python崇尚「鴨子類型」。

  • Python僞代碼實現Java或C#的多態
class F1:
    pass


class S1(F1):

    def show(self):
        print 'S1.show'


class S2(F1):

    def show(self):
        print 'S2.show'


# 因爲在Java或C#中定義函數參數時,必須指定參數的類型
# 爲了讓Func函數既能夠執行S1對象的show方法,又能夠執行S2對象的show方法,因此,定義了一個S1和S2類的父類
# 而實際傳入的參數是:S1對象和S2對象

def Func(F1 obj):
    """Func函數須要接收一個F1類型或者F1子類的類型"""
    
    print obj.show()
    
s1_obj = S1()
Func(s1_obj) # 在Func函數中傳入S1類的對象 s1_obj,執行 S1 的show方法,結果:S1.show

s2_obj = S2()
Func(s2_obj) # 在Func函數中傳入Ss類的對象 ss_obj,執行 Ss 的show方法,結果:S2.show
  • Python 「鴨子類型」
class F1:
    pass


class S1(F1):

    def show(self):
        print 'S1.show'


class S2(F1):

    def show(self):
        print 'S2.show'

def Func(obj):
    print obj.show()

s1_obj = S1()
Func(s1_obj) 

s2_obj = S2()
Func(s2_obj) 

總結 

以上就是本節對於面向對象初級知識的介紹,總結以下:

  • 面向對象是一種編程方式,此編程方式的實現是基於對  和 對象 的使用
  • 類 是一個模板,模板中包裝了多個「函數」供使用
  • 對象,根據模板建立的實例(即:對象),實例用於調用被包裝在類中的函數
  • 面向對象三大特性:封裝、繼承和多態
相關文章
相關標籤/搜索