Open2

ジェンダーをオブジェクトモデルで明確に表現したい

Hidden comment
きょきょ

版2:

現状、ジェンダーにおける「性的指向」と「恋愛指向」という概念は、その定義が曖昧で、混乱を招くことがある。

https://jobrainbow.jp/magazine/heterosexual

一口に「異性」といったところで、自身とちがう身体的性を指して「異性」と呼ぶのか、自身とちがう性自認を指して「異性」と呼ぶのか、自身とちがう性表現を指して「異性」と呼ぶのか……はたまた、そのどれもが自分とちがう場合を指すのか。そこがきわめて曖昧なんです。

個人の性的指向、あるいは恋愛指向を算出する場合、必要なプロパティとして個人のジェンダーと相手のジェンダーが必要になるが、個人に対して定義できるジェンダーには複数の種類が存在する。ここでは個人のジェンダーの属性として、身体的性、性自認、性表現が挙げられるとする。すると、性的指向、恋愛指向というものはこれらのそれぞれについて算出することができる。

これら二つの概念の定義として、個人のジェンダーには複数の属性があることを考慮せず、個人のジェンダーを一つの属性、つまり「男性」か「女性」かにまとめてしまうと、例えば、「身体的にはヘテロセクシャルであっても、性自認ではホモセクシャル」などのケースを表現することができない。

従来のジェンダーの分類では、十分にジェンダーのあり方を表現することができず、自らと相手のジェンダーを参照して相性マッチングを行なった場合に、ミスマッチが起こる可能性が考えられた。
身体的性、性自認、性表現のそれぞれに性的指向と恋愛指向を定義することによって、これを解消することができる。

ここで、個人のジェンダーを明快に表現するために、ジェンダーをオブジェクトモデルとそのプロパティで明快に表現したいという動機がある。

以下は、PythonのPydanticモデルで作成したGenderモデルである。現状、仮として身体的性(biological_gender)は-1(Female), 1(Male), 0(Others), そのほかの性(性自認、性表現、 身体的性的指向、性自認的性的指向、性表現的性的指向、身体的恋愛指向、性自認的恋愛指向、性表現的恋愛指向)は-1~1のスライダーでプロパティの型を設定している。

オブジェクトモデルについては改善の余地がある。なぜならば、性的指向、恋愛指向は必ずしも一つの値であるとは限らないからである。また、身体的性も、MaleとFemaleのバイナリであるとは限らない。Othersという値を用意してあるが、モデルは不十分である。

プロパティでは、身体的性、性自認、性表現のそれぞれについて性的位置(gender alignment)と、身体的性と性自認を比較してシス・トランスの判定を出している。

from typing import Literal

from pydantic import BaseModel, confloat, field_validator


def is_numeric(value: any) -> bool:
    return isinstance(value, (int, float))


class Gender(BaseModel):
    biological_gender: Literal[-1, 1, 0]
    gender_identity: confloat(ge=-1, le=1)
    gender_expression: confloat(ge=-1, le=1)

    biological_gender_sexual_orientation: confloat(ge=-1, le=1)
    gender_identity_sexual_orientation: confloat(ge=-1, le=1)
    gender_expression_sexual_orientation: confloat(ge=-1, le=1)

    biological_gender_romantic_orientation: confloat(ge=-1, le=1)
    gender_identity_romantic_orientation: confloat(ge=-1, le=1)
    gender_expression_romantic_orientation: confloat(ge=-1, le=1)

    @field_validator("biological_gender", mode="before")
    def validate_biological_gender(cls, value):
        if value == "M":
            return 1
        elif value == "F":
            return -1
        return 0

    @field_validator(
        "gender_identity",
        "gender_expression",
        "biological_gender_sexual_orientation",
        "gender_identity_sexual_orientation",
        "gender_expression_sexual_orientation",
        "biological_gender_romantic_orientation",
        "gender_identity_romantic_orientation",
        "gender_expression_romantic_orientation",
        mode="before",
    )
    def validate_other_genders(cls, value):
        if value in ["M", "F"]:
            if value == "M":
                return 1
            else:
                return -1

        if isinstance(value, (int, float)):
            if value < -1 or value > 1:
                raise ValueError("value must be in range -1 to 1")
            return value

    @property
    def biological_gender_sexual_alignment(self) -> str:
        d = abs(self.biological_gender - self.biological_gender_sexual_orientation)
        if d < 1:
            return "BodyHomosexual"
        else:
            return "BodyHeterosexual"

    @property
    def gender_identity_sexual_alignment(self) -> str:
        d = abs(self.gender_identity - self.gender_identity_sexual_orientation)
        if d < 1:
            return "IdentityHomosexual"
        else:
            return "IdentityHeterosexual"

    @property
    def gender_expression_sexual_alignment(self) -> str:
        d = abs(self.gender_expression - self.gender_expression_sexual_orientation)
        if d < 1:
            return "ExpressionHomosexual"
        else:
            return "ExpressionHeterosexual"

    @property
    def biological_gender_romantic_alignment(self) -> str:
        d = abs(self.biological_gender - self.biological_gender_romantic_orientation)
        if d < 1:
            return "BodyHomoromantic"
        else:
            return "BodyHeteroRomantic"

    @property
    def gender_identity_romantic_alignment(self) -> str:
        d = abs(self.gender_identity - self.gender_identity_romantic_orientation)
        if d < 1:
            return "IdentityHomoromantic"
        else:
            return "IdentityHeteroRomantic"

    @property
    def gender_expression_romantic_alignment(self) -> str:
        d = abs(self.gender_expression - self.gender_expression_romantic_orientation)
        if d < 1:
            return "ExpressionHomoromantic"
        else:
            return "ExpressionHeteroRomantic"

    @property
    def gender_alignment(self) -> str:
        if self.gender_identity == self.biological_gender:
            return "Cisgender"
        else:
            return "Transgender"


# 使用例
gender = Gender(
    biological_gender="M",
    gender_identity="F",
    gender_expression="M",
    biological_gender_sexual_orientation="M",
    gender_identity_sexual_orientation="M",
    gender_expression_sexual_orientation="F",
    biological_gender_romantic_orientation="M",
    gender_identity_romantic_orientation="F",
    gender_expression_romantic_orientation="M",
)

print(gender.biological_gender_sexual_alignment)
print(gender.biological_gender_romantic_alignment)
print(gender.gender_identity_sexual_alignment)
print(gender.gender_identity_romantic_alignment)
print(gender.gender_expression_sexual_alignment)
print(gender.gender_expression_romantic_alignment)
print(gender.gender_alignment)
output
> rye run python a.py
BodyHomosexual
BodyHomoromantic
IdentityHeterosexual
IdentityHomoromantic
ExpressionHeterosexual
ExpressionHomoromantic
Transgender