python-3.x umlaute - Was ist der beste Weg, um Akzente in einer Python-Unicode-Zeichenkette zu entfernen?





ersetzen utf-8 (9)


In einigen Sprachen werden diakritische Zeichen als Sprachbuchstaben und Akzentzeichen als Akzente verwendet.

Ich denke, es ist sicherer, explizit anzugeben, welche diaktrischen Elemente entfernt werden sollen:

def strip_accents(string, accents=('COMBINING ACUTE ACCENT', 'COMBINING GRAVE ACCENT', 'COMBINING TILDE')):
    accents = set(map(unicodedata.lookup, accents))
    chars = [c for c in unicodedata.normalize('NFD', string) if c not in accents]
    return unicodedata.normalize('NFC', ''.join(chars))

Ich habe eine Unicode-Zeichenfolge in Python, und ich möchte alle Akzente (Diakritika) entfernen.

Ich habe im Web einen eleganten Weg gefunden, dies in Java zu tun:

  1. Konvertieren Sie die Unicode-Zeichenfolge in ihre lange normalisierte Form (mit einem separaten Zeichen für Buchstaben und diakritische Zeichen)
  2. Entfernen Sie alle Zeichen, deren Unicode-Typ "diakritisch" ist.

Muss ich eine Bibliothek wie pyICU installieren oder ist dies nur mit der Python-Standardbibliothek möglich? Und was ist mit Python 3?

Wichtiger Hinweis: Ich möchte Code mit einer expliziten Zuordnung von Akzentzeichen zu ihrem nicht akzentuierten Gegenstück vermeiden.




Ich habe diese Antwort im Web gefunden:

import unicodedata

def remove_accents(input_str):
    nfkd_form = unicodedata.normalize('NFKD', input_str)
    only_ascii = nfkd_form.encode('ASCII', 'ignore')
    return only_ascii

Es funktioniert gut (zum Beispiel für Französisch), aber ich denke, der zweite Schritt (das Entfernen der Akzente) könnte besser gehandhabt werden als das Löschen der Nicht-ASCII-Zeichen, weil dies bei einigen Sprachen fehlschlägt (zB Griechisch). Die beste Lösung wäre wahrscheinlich, die Unicode-Zeichen, die als diakritisch gekennzeichnet sind, explizit zu entfernen.

Edit : Das macht den Trick:

import unicodedata

def remove_accents(input_str):
    nfkd_form = unicodedata.normalize('NFKD', input_str)
    return u"".join([c for c in nfkd_form if not unicodedata.combining(c)])

unicodedata.combining(c) gibt true zurück, wenn das Zeichen c mit dem vorhergehenden Zeichen kombiniert werden kann, also hauptsächlich wenn es sich um ein diakritisches Zeichen handelt.

Edit 2 : remove_accents erwartet eine Unicode- Zeichenfolge, keine Byte-Zeichenfolge. Wenn Sie eine Byte-Zeichenfolge haben, müssen Sie sie in eine Unicode-Zeichenfolge wie folgt dekodieren:

encoding = "utf-8" # or iso-8859-15, or cp1252, or whatever encoding you use
byte_string = b"café"  # or simply "café" before python 3.
unicode_string = byte_string.decode(encoding)



Unidecode ist die richtige Antwort dafür. Es transkribiert jede Unicode-Zeichenfolge in die nächstmögliche Darstellung in Ascii-Text.

Beispiel:

accented_string = u'Málaga'
# accented_string is of type 'unicode'
import unidecode
unaccented_string = unidecode.unidecode(accented_string)
# unaccented_string contains 'Malaga'and is of type 'str'



Wie wäre es damit:

import unicodedata
def strip_accents(s):
   return ''.join(c for c in unicodedata.normalize('NFD', s)
                  if unicodedata.category(c) != 'Mn')

Dies funktioniert auch mit griechischen Buchstaben:

>>> strip_accents(u"A \u00c0 \u0394 \u038E")
u'A A \u0394 \u03a5'
>>> 

Die Zeichenkategorie "Mn" steht für Nonspacing_Mark , was in der Antwort von MiniQuark ähnlich ist wie unicodeata.combining (ich dachte nicht an unicodedata.combining, aber es ist wahrscheinlich die bessere Lösung, weil es expliziter ist).

Und bedenken Sie, diese Manipulationen können die Bedeutung des Textes erheblich verändern. Akzente, Umlaute etc. sind keine "Dekoration".




Eigentlich arbeite ich an projektkompatiblen Python 2.6, 2.7 und 3.4 und ich muss IDs aus freien Benutzereinträgen erstellen.

Dank dir habe ich diese Funktion geschaffen, die Wunder wirkt.

import re
import unicodedata

def strip_accents(text):
    """
    Strip accents from input String.

    :param text: The input string.
    :type text: String.

    :returns: The processed String.
    :rtype: String.
    """
    try:
        text = unicode(text, 'utf-8')
    except (TypeError, NameError): # unicode is a default on python 3 
        pass
    text = unicodedata.normalize('NFD', text)
    text = text.encode('ascii', 'ignore')
    text = text.decode("utf-8")
    return str(text)

def text_to_id(text):
    """
    Convert input text to id.

    :param text: The input string.
    :type text: String.

    :returns: The processed String.
    :rtype: String.
    """
    text = strip_accents(text.lower())
    text = re.sub('[ ]+', '_', text)
    text = re.sub('[^0-9a-zA-Z_-]', '', text)
    return text

Ergebnis:

text_to_id("Montréal, über, 12.89, Mère, Françoise, noël, 889")
>>> 'montreal_uber_1289_mere_francoise_noel_889'



gensim.utils.deaccent(text) von Gensim - Thema Modellierung für Menschen :

deaccent("Šéf chomutovských komunistů dostal poštou bílý prášek") 'Sef chomutovskych komunistu dostal postou bily prasek'

Eine andere Lösung ist Unidecode .

Nicht, dass die vorgeschlagene Lösung mit UnicodeData typischerweise Akzente nur in einem bestimmten Zeichen entfernt (z. B. macht es 'ł' in '' statt in 'l' ).




Dies behandelt nicht nur Akzente, sondern auch "Striche" (wie bei ø etc.):

import unicodedata as ud

def rmdiacritics(char):
    '''
    Return the base character of char, by "removing" any
    diacritics like accents or curls and strokes and the like.
    '''
    desc = ud.name(unicode(char))
    cutoff = desc.find(' WITH ')
    if cutoff != -1:
        desc = desc[:cutoff]
    return ud.lookup(desc)

Dies ist die eleganteste Art und Weise, die ich mir vorstellen kann (und es wurde von Alexis in einem Kommentar auf dieser Seite erwähnt), obwohl ich nicht denke, dass es wirklich sehr elegant ist.

Es gibt immer noch spezielle Buchstaben, die nicht behandelt werden, wie zum Beispiel umgedrehte und invertierte Buchstaben, da ihr Unicode-Name kein 'WITH' enthält. Es hängt davon ab, was du sowieso machen willst. Manchmal brauchte ich Akzent-Stripping, um die Sortierreihenfolge der Wörterbücher zu erreichen.




Als Antwort auf @ MiniQuarks Antwort:

Ich habe versucht, in einer csv-Datei zu lesen, die halb Französisch war (mit Akzenten) und auch einige Strings, die schließlich zu Integers und Floats werden würden. Als Test habe ich eine test.txt Datei erstellt, die wie test.txt :

Montréal, über, 12.89, Mère, Françoise, noël, 889

Ich musste Zeilen 2 und 3 einfügen, um es zum Laufen zu bringen (was ich in einem Python-Ticket gefunden habe), und auch @ Jabbas Kommentar einbeziehen:

import sys 
reload(sys) 
sys.setdefaultencoding("utf-8")
import csv
import unicodedata

def remove_accents(input_str):
    nkfd_form = unicodedata.normalize('NFKD', unicode(input_str))
    return u"".join([c for c in nkfd_form if not unicodedata.combining(c)])

with open('test.txt') as f:
    read = csv.reader(f)
    for row in read:
        for element in row:
            print remove_accents(element)

Das Ergebnis:

Montreal
uber
12.89
Mere
Francoise
noel
889

(Hinweis: Ich bin auf Mac OS X 10.8.4 und mit Python 2.7.3)




Klassenmethode vs. statische Methode in Python

Klassenmethode

Der @classmethod-Dekorator, ein eingebauter Funktionsdekorator, ist ein Ausdruck, der ausgewertet wird, nachdem Ihre Funktion definiert wurde. Das Ergebnis dieser Auswertung zeigt Ihre Funktionsdefinition.

Eine Klassenmethode empfängt die Klasse als implizites erstes Argument, genau wie eine Instanzmethode die Instanz

Syntax:

class C(object):
    @staticmethod
    def fun(arg1, arg2, ...):
        ...
returns: a static method for function fun.
  • Eine Klassenmethode ist eine Methode, die an die Klasse und nicht an das Objekt der Klasse gebunden ist.
  • Sie haben Zugriff auf den Status der Klasse, da sie einen Klassenparameter benötigt, der auf die Klasse und nicht auf die Objektinstanz verweist.
  • Es kann einen Klassenstatus ändern, der für alle Instanzen der Klasse gelten würde. Beispielsweise kann eine Klassenvariable geändert werden, die auf alle Instanzen anwendbar ist.

Statische Methode

Eine statische Methode erhält kein implizites erstes Argument.

Syntax:

# Python program to demonstrate 
# use of class method and static method.
from datetime import date

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # a class method to create a Person object by birth year.
    @classmethod
    def fromBirthYear(cls, name, year):
        return cls(name, date.today().year - year)

    # a static method to check if a Person is adult or not.
    @staticmethod
    def isAdult(age):
        return age > 18

person1 = Person('mayank', 21)
person2 = Person.fromBirthYear('mayank', 1996)

print person1.age
print person2.age

# print the result
print Person.isAdult(22)
  • Eine statische Methode ist auch eine Methode, die an die Klasse und nicht an das Objekt der Klasse gebunden ist.
  • Eine statische Methode kann nicht auf den Klassenstatus zugreifen oder diesen ändern.
  • Es ist in einer Klasse vorhanden, weil es sinnvoll ist, dass die Methode in der Klasse vorhanden ist.

Klassenmethode vs. statische Methode

  • Eine Klassenmethode verwendet cls als ersten Parameter, während eine statische Methode keine spezifischen Parameter benötigt.
  • Eine Klassenmethode kann auf den Klassenstatus zugreifen oder diesen ändern, während eine statische Methode nicht auf ihn zugreifen oder ihn ändern kann.
  • Wir verwenden @classmethod decorator in python, um eine Klassenmethode zu erstellen, und wir verwenden @staticmethod decorator, um eine statische Methode in python zu erstellen.

Wann was verwenden?

  • Im Allgemeinen verwenden wir Klassenmethoden, um Factory-Methoden zu erstellen. Factory-Methoden geben Klassenobjekte (ähnlich einem Konstruktor) für verschiedene Anwendungsfälle zurück.
  • Im Allgemeinen verwenden wir statische Methoden, um Hilfsfunktionen zu erstellen.

Wie definiere ich eine Klassenmethode und eine statische Methode?

Um eine Klassenmethode in Python zu definieren, verwenden wir @classmethod decorator und zur Definition einer statischen Methode verwenden wir @staticmethod decorator.

Schauen wir uns ein Beispiel an, um den Unterschied zwischen beiden zu verstehen. Nehmen wir an, wir möchten eine Klasse Person erstellen. Jetzt unterstützt Python keine Methodenüberladung wie C ++ oder Java. Daher verwenden wir Klassenmethoden, um Factory-Methoden zu erstellen. Im folgenden Beispiel verwenden wir eine Klassenmethode, um ein Personenobjekt aus dem Geburtsjahr zu erstellen.

Wie oben erläutert, verwenden wir statische Methoden, um Hilfsfunktionen zu erstellen. Im folgenden Beispiel verwenden wir eine statische Methode, um zu prüfen, ob eine Person erwachsen ist oder nicht.

Implementierung

21
21
True

Ausgabe

>>> class Klaus:
        @classmethod
        def classmthd(*args):
            return args

        @staticmethod
        def staticmthd(*args):
            return args

# 1. Call classmethod without any arg
>>> Klaus.classmthd()  
(__main__.Klaus,)  # the class gets passed as the first argument

# 2. Call classmethod with 1 arg
>>> Klaus.classmthd('chumma')
(__main__.Klaus, 'chumma')

# 3. Call staticmethod without any arg
>>> Klaus.staticmthd()  
()

# 4. Call staticmethod with 1 arg
>>> Klaus.staticmthd('chumma')
('chumma',)

Reference







python python-3.x unicode python-2.x diacritics