Repository: Pycord-Development/pycord

Issue:
Querying the member_count property on a discord.guild.Guild object gives the error AttributeError("'Guild' object has no attribute '_member_count'") 
### Summary

Querying the member_count property on a discord.guild.Guild object gives the error AttributeError("'Guild' object has no attribute '_member_count'") 

### Reproduction Steps

Query the `member_count` property on a discord guild object, like shown in the code below

### Minimal Reproducible Code

```python
from   discord.ext import commands
import discord

from rich import inspect

import json





# Loads the config
with open('config.json') as f:
    config:dict = json.load(f)




intents = discord.Intents.default()
intents.members = True
bot     = commands.Bot(intents=intents)


@bot.event
async def on_ready():
    # Get info of all the guilds
    async for guild in bot.fetch_guilds():
        actual_guild = await bot.fetch_guild(guild.id, with_counts=True)
        inspect(actual_guild)
        print(actual_guild.member_count)
    
    await bot.close()



bot.run(config['token'])
```


### Expected Results

The count of members to be shown

### Actual Results

It raised an error. This is the output:

![Screenshot 2023-06-21 at 8 06 04 PM](https://github.com/Pycord-Development/pycord/assets/79649185/b334e775-99a8-4936-868a-dab2b0801f22)

![Screenshot 2023-06-21 at 8 06 38 PM](https://github.com/Pycord-Development/pycord/assets/79649185/f241f6d8-1f4b-4d1b-9152-878c09349e79)


### Intents

the default ones and the member one

### System Information

```
- Python v3.11.3-final
- py-cord v2.4.1-final
- aiohttp v3.8.4
- system info: Darwin 21.6.0 Darwin Kernel Version 21.6.0: Mon Dec 19 20:44:01 PST 2022; root:xnu-8020.240.18~2/RELEASE_X86_64
```

### Checklist

- [X] I have searched the open issues for duplicates.
- [X] I have shown the entire traceback, if possible.
- [X] I have removed my token from display, if visible.

### Additional Context

_No response_


Discussion:
If you use `fetch_guild`, you should be using `Guild.approximate_member_count`
That being said, this can still be considered a bug as the attribute should be set regardless.

Resolving patch:
diff --git a/discord/guild.py b/discord/guild.py
--- a/discord/guild.py
+++ b/discord/guild.py
@@ -383,7 +383,7 @@ def __repr__(self) -> str:
             ("name", self.name),
             ("shard_id", self.shard_id),
             ("chunked", self.chunked),
-            ("member_count", getattr(self, "_member_count", None)),
+            ("member_count", self._member_count),
         )
         inner = " ".join("%s=%r" % t for t in attrs)
         return f"<Guild {inner}>"
@@ -441,11 +441,11 @@ def _remove_role(self, role_id: int, /) -> Role:
         return role
 
     def _from_data(self, guild: GuildPayload) -> None:
-        # according to Stan, this is always available even if the guild is unavailable
-        # I don't have this guarantee when someone updates the guild.
-        member_count = guild.get("member_count", None)
-        if member_count is not None:
-            self._member_count: int = member_count
+        member_count = guild.get("member_count")
+        # Either the payload includes member_count, or it hasn't been set yet.
+        # Prevents valid _member_count from suddenly changing to None
+        if member_count is not None or not hasattr(self, "_member_count"):
+            self._member_count: int | None = member_count
 
         self.name: str = guild.get("name")
         self.verification_level: VerificationLevel = try_enum(
@@ -532,7 +532,7 @@ def _from_data(self, guild: GuildPayload) -> None:
 
         self._sync(guild)
         self._large: bool | None = (
-            None if member_count is None else self._member_count >= 250
+            None if self._member_count is None else self._member_count >= 250
         )
 
         self.owner_id: int | None = utils._get_as_snowflake(guild, "owner_id")
@@ -598,10 +598,7 @@ def large(self) -> bool:
         members, which for this library is set to the maximum of 250.
         """
         if self._large is None:
-            try:
-                return self._member_count >= 250
-            except AttributeError:
-                return len(self._members) >= 250
+            return (self._member_count or len(self._members)) >= 250
         return self._large
 
     @property
@@ -1002,10 +999,9 @@ def chunked(self) -> bool:
         If this value returns ``False``, then you should request for
         offline members.
         """
-        count = getattr(self, "_member_count", None)
-        if count is None:
+        if self._member_count is None:
             return False
-        return count == len(self._members)
+        return self._member_count == len(self._members)
 
     @property
     def shard_id(self) -> int:
diff --git a/discord/state.py b/discord/state.py
--- a/discord/state.py
+++ b/discord/state.py
@@ -1139,10 +1139,8 @@ def parse_guild_member_add(self, data) -> None:
         if self.member_cache_flags.joined:
             guild._add_member(member)
 
-        try:
+        if guild._member_count is not None:
             guild._member_count += 1
-        except AttributeError:
-            pass
 
         self.dispatch("member_join", member)
 
@@ -1152,10 +1150,8 @@ def parse_guild_member_remove(self, data) -> None:
 
         guild = self._get_guild(int(data["guild_id"]))
         if guild is not None:
-            try:
+            if guild._member_count is not None:
                 guild._member_count -= 1
-            except AttributeError:
-                pass
 
             member = guild.get_member(user.id)
             if member is not None:


Test patch: